Accepting request 373092 from systemsmanagement:saltstack
1 OBS-URL: https://build.opensuse.org/request/show/373092 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=57
This commit is contained in:
commit
fbcc3f837b
734
0029-Make-use-of-checksum-configurable-defaults-to-MD5-SH.patch
Normal file
734
0029-Make-use-of-checksum-configurable-defaults-to-MD5-SH.patch
Normal file
@ -0,0 +1,734 @@
|
||||
From 2220c5a0ae800988bf83c39b458a8747f01186c0 Mon Sep 17 00:00:00 2001
|
||||
From: Bo Maryniuk <bo@suse.de>
|
||||
Date: Fri, 12 Feb 2016 16:16:12 +0100
|
||||
Subject: [PATCH 29/29] Make use of checksum configurable (defaults to MD5,
|
||||
SHA256 suggested)
|
||||
|
||||
Set config hash_type to SHA1
|
||||
Set default hash as SHA1 in config and explain why.
|
||||
Use hash_type configuration for the Cloud
|
||||
Use configurable hash_type for general Key fingerprinting
|
||||
Use SHA1 hash by default
|
||||
Use SHA1 hash by default in Tomcat module, refactor for support different algorithms
|
||||
Use SHA1 by default instead of MD5
|
||||
Remove SHA1 to SHA265 by default
|
||||
Add note to the Tomcat module for SHA256
|
||||
Remove sha1 to sha265
|
||||
Remove SHA1 for SHA256
|
||||
Remove SHA1 in favor of SHA256
|
||||
Use MD5 hash algorithm by default (until deprecated)
|
||||
Create a mixin class that will be reused in the similar instances (daemons)
|
||||
Use mixin for the daemon classes
|
||||
Report environment failure, if any
|
||||
Verify if hash_type is using vulnerable algorithms
|
||||
Standardize logging
|
||||
Add daemons unit test to verify hash_type settings
|
||||
Fix PyLint
|
||||
---
|
||||
conf/master | 5 +-
|
||||
conf/minion | 8 +-
|
||||
conf/proxy | 9 +-
|
||||
salt/cli/daemons.py | 83 +++++++++++++-----
|
||||
salt/cloud/__init__.py | 4 +-
|
||||
salt/crypt.py | 10 +--
|
||||
salt/key.py | 4 +-
|
||||
salt/modules/key.py | 10 +--
|
||||
salt/modules/tomcat.py | 26 ++----
|
||||
salt/modules/win_file.py | 2 +-
|
||||
salt/utils/__init__.py | 13 +--
|
||||
salt/utils/cloud.py | 3 +-
|
||||
tests/unit/daemons_test.py | 209 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
13 files changed, 319 insertions(+), 67 deletions(-)
|
||||
create mode 100644 tests/unit/daemons_test.py
|
||||
|
||||
diff --git a/conf/master b/conf/master
|
||||
index 36657e8..cf05ec4 100644
|
||||
--- a/conf/master
|
||||
+++ b/conf/master
|
||||
@@ -466,9 +466,12 @@ syndic_user: salt
|
||||
#default_top: base
|
||||
|
||||
# The hash_type is the hash to use when discovering the hash of a file on
|
||||
-# the master server. The default is md5, but sha1, sha224, sha256, sha384
|
||||
+# the master server. The default is md5 but sha1, sha224, sha256, sha384
|
||||
# and sha512 are also supported.
|
||||
#
|
||||
+# WARNING: While md5 is supported, do not use it due to the high chance
|
||||
+# of possible collisions and thus security breach.
|
||||
+#
|
||||
# Prior to changing this value, the master should be stopped and all Salt
|
||||
# caches should be cleared.
|
||||
#hash_type: md5
|
||||
diff --git a/conf/minion b/conf/minion
|
||||
index 2307f70..e17ec61 100644
|
||||
--- a/conf/minion
|
||||
+++ b/conf/minion
|
||||
@@ -440,12 +440,14 @@
|
||||
#fileserver_limit_traversal: False
|
||||
|
||||
# The hash_type is the hash to use when discovering the hash of a file in
|
||||
-# the local fileserver. The default is md5, but sha1, sha224, sha256, sha384
|
||||
-# and sha512 are also supported.
|
||||
+# the local fileserver. The default is sha256, sha224, sha384 and sha512 are also supported.
|
||||
+#
|
||||
+# WARNING: While md5 and sha1 are also supported, do not use it due to the high chance
|
||||
+# of possible collisions and thus security breach.
|
||||
#
|
||||
# Warning: Prior to changing this value, the minion should be stopped and all
|
||||
# Salt caches should be cleared.
|
||||
-#hash_type: md5
|
||||
+#hash_type: sha256
|
||||
|
||||
# The Salt pillar is searched for locally if file_client is set to local. If
|
||||
# this is the case, and pillar data is defined, then the pillar_roots need to
|
||||
diff --git a/conf/proxy b/conf/proxy
|
||||
index 472df35..0de6af8 100644
|
||||
--- a/conf/proxy
|
||||
+++ b/conf/proxy
|
||||
@@ -419,12 +419,15 @@
|
||||
#fileserver_limit_traversal: False
|
||||
|
||||
# The hash_type is the hash to use when discovering the hash of a file in
|
||||
-# the local fileserver. The default is md5, but sha1, sha224, sha256, sha384
|
||||
-# and sha512 are also supported.
|
||||
+# the local fileserver. The default is sha256 but sha224, sha384 and sha512
|
||||
+# are also supported.
|
||||
+#
|
||||
+# WARNING: While md5 and sha1 are also supported, do not use it due to the high chance
|
||||
+# of possible collisions and thus security breach.
|
||||
#
|
||||
# Warning: Prior to changing this value, the minion should be stopped and all
|
||||
# Salt caches should be cleared.
|
||||
-#hash_type: md5
|
||||
+#hash_type: sha256
|
||||
|
||||
# The Salt pillar is searched for locally if file_client is set to local. If
|
||||
# this is the case, and pillar data is defined, then the pillar_roots need to
|
||||
diff --git a/salt/cli/daemons.py b/salt/cli/daemons.py
|
||||
index 7f8b8c8..b0e7b20 100644
|
||||
--- a/salt/cli/daemons.py
|
||||
+++ b/salt/cli/daemons.py
|
||||
@@ -58,7 +58,50 @@ from salt.exceptions import SaltSystemExit
|
||||
logger = salt.log.setup.logging.getLogger(__name__)
|
||||
|
||||
|
||||
-class Master(parsers.MasterOptionParser):
|
||||
+class DaemonsMixin(object): # pylint: disable=no-init
|
||||
+ '''
|
||||
+ Uses the same functions for all daemons
|
||||
+ '''
|
||||
+ def verify_hash_type(self):
|
||||
+ '''
|
||||
+ Verify and display a nag-messsage to the log if vulnerable hash-type is used.
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+ if self.config['hash_type'].lower() in ['md5', 'sha1']:
|
||||
+ logger.warning('IMPORTANT: Do not use {h_type} hashing algorithm! Please set "hash_type" to '
|
||||
+ 'SHA256 in Salt {d_name} config!'.format(
|
||||
+ h_type=self.config['hash_type'], d_name=self.__class__.__name__))
|
||||
+
|
||||
+ def start_log_info(self):
|
||||
+ '''
|
||||
+ Say daemon starting.
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+ logger.info('The Salt {d_name} is starting up'.format(d_name=self.__class__.__name__))
|
||||
+
|
||||
+ def shutdown_log_info(self):
|
||||
+ '''
|
||||
+ Say daemon shutting down.
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+ logger.info('The Salt {d_name} is shut down'.format(d_name=self.__class__.__name__))
|
||||
+
|
||||
+ def environment_failure(self, error):
|
||||
+ '''
|
||||
+ Log environment failure for the daemon and exit with the error code.
|
||||
+
|
||||
+ :param error:
|
||||
+ :return:
|
||||
+ '''
|
||||
+ logger.exception('Failed to create environment for {d_name}: {reason}'.format(
|
||||
+ d_name=self.__class__.__name__, reason=error.message))
|
||||
+ sys.exit(error.errno)
|
||||
+
|
||||
+
|
||||
+class Master(parsers.MasterOptionParser, DaemonsMixin): # pylint: disable=no-init
|
||||
'''
|
||||
Creates a master server
|
||||
'''
|
||||
@@ -114,8 +157,7 @@ class Master(parsers.MasterOptionParser):
|
||||
for syndic_file in os.listdir(self.config['syndic_dir']):
|
||||
os.remove(os.path.join(self.config['syndic_dir'], syndic_file))
|
||||
except OSError as err:
|
||||
- logger.exception('Failed to prepare salt environment')
|
||||
- sys.exit(err.errno)
|
||||
+ self.environment_failure(err)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
@@ -153,17 +195,18 @@ class Master(parsers.MasterOptionParser):
|
||||
'''
|
||||
self.prepare()
|
||||
if check_user(self.config['user']):
|
||||
- logger.info('The salt master is starting up')
|
||||
+ self.verify_hash_type()
|
||||
+ self.start_log_info()
|
||||
self.master.start()
|
||||
|
||||
def shutdown(self):
|
||||
'''
|
||||
If sub-classed, run any shutdown operations on this method.
|
||||
'''
|
||||
- logger.info('The salt master is shut down')
|
||||
+ self.shutdown_log_info()
|
||||
|
||||
|
||||
-class Minion(parsers.MinionOptionParser): # pylint: disable=no-init
|
||||
+class Minion(parsers.MinionOptionParser, DaemonsMixin): # pylint: disable=no-init
|
||||
'''
|
||||
Create a minion server
|
||||
'''
|
||||
@@ -226,8 +269,7 @@ class Minion(parsers.MinionOptionParser): # pylint: disable=no-init
|
||||
verify_files([logfile], self.config['user'])
|
||||
os.umask(current_umask)
|
||||
except OSError as err:
|
||||
- logger.exception('Failed to prepare salt environment')
|
||||
- sys.exit(err.errno)
|
||||
+ self.environment_failure(err)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
@@ -273,7 +315,8 @@ class Minion(parsers.MinionOptionParser): # pylint: disable=no-init
|
||||
try:
|
||||
self.prepare()
|
||||
if check_user(self.config['user']):
|
||||
- logger.info('The salt minion is starting up')
|
||||
+ self.verify_hash_type()
|
||||
+ self.start_log_info()
|
||||
self.minion.tune_in()
|
||||
finally:
|
||||
self.shutdown()
|
||||
@@ -310,10 +353,10 @@ class Minion(parsers.MinionOptionParser): # pylint: disable=no-init
|
||||
'''
|
||||
If sub-classed, run any shutdown operations on this method.
|
||||
'''
|
||||
- logger.info('The salt minion is shut down')
|
||||
+ self.shutdown_log_info()
|
||||
|
||||
|
||||
-class ProxyMinion(parsers.ProxyMinionOptionParser): # pylint: disable=no-init
|
||||
+class ProxyMinion(parsers.ProxyMinionOptionParser, DaemonsMixin): # pylint: disable=no-init
|
||||
'''
|
||||
Create a proxy minion server
|
||||
'''
|
||||
@@ -388,8 +431,7 @@ class ProxyMinion(parsers.ProxyMinionOptionParser): # pylint: disable=no-init
|
||||
os.umask(current_umask)
|
||||
|
||||
except OSError as err:
|
||||
- logger.exception('Failed to prepare salt environment')
|
||||
- sys.exit(err.errno)
|
||||
+ self.environment_failure(err)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
@@ -431,7 +473,8 @@ class ProxyMinion(parsers.ProxyMinionOptionParser): # pylint: disable=no-init
|
||||
try:
|
||||
self.prepare()
|
||||
if check_user(self.config['user']):
|
||||
- logger.info('The proxy minion is starting up')
|
||||
+ self.verify_hash_type()
|
||||
+ self.start_log_info()
|
||||
self.minion.tune_in()
|
||||
except (KeyboardInterrupt, SaltSystemExit) as exc:
|
||||
logger.warn('Stopping the Salt Proxy Minion')
|
||||
@@ -449,10 +492,10 @@ class ProxyMinion(parsers.ProxyMinionOptionParser): # pylint: disable=no-init
|
||||
if hasattr(self, 'minion') and 'proxymodule' in self.minion.opts:
|
||||
proxy_fn = self.minion.opts['proxymodule'].loaded_base_name + '.shutdown'
|
||||
self.minion.opts['proxymodule'][proxy_fn](self.minion.opts)
|
||||
- logger.info('The proxy minion is shut down')
|
||||
+ self.shutdown_log_info()
|
||||
|
||||
|
||||
-class Syndic(parsers.SyndicOptionParser):
|
||||
+class Syndic(parsers.SyndicOptionParser, DaemonsMixin): # pylint: disable=no-init
|
||||
'''
|
||||
Create a syndic server
|
||||
'''
|
||||
@@ -488,8 +531,7 @@ class Syndic(parsers.SyndicOptionParser):
|
||||
verify_files([logfile], self.config['user'])
|
||||
os.umask(current_umask)
|
||||
except OSError as err:
|
||||
- logger.exception('Failed to prepare salt environment')
|
||||
- sys.exit(err.errno)
|
||||
+ self.environment_failure(err)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
@@ -521,7 +563,8 @@ class Syndic(parsers.SyndicOptionParser):
|
||||
'''
|
||||
self.prepare()
|
||||
if check_user(self.config['user']):
|
||||
- logger.info('The salt syndic is starting up')
|
||||
+ self.verify_hash_type()
|
||||
+ self.start_log_info()
|
||||
try:
|
||||
self.syndic.tune_in()
|
||||
except KeyboardInterrupt:
|
||||
@@ -532,4 +575,4 @@ class Syndic(parsers.SyndicOptionParser):
|
||||
'''
|
||||
If sub-classed, run any shutdown operations on this method.
|
||||
'''
|
||||
- logger.info('The salt syndic is shut down')
|
||||
+ self.shutdown_log_info()
|
||||
diff --git a/salt/cloud/__init__.py b/salt/cloud/__init__.py
|
||||
index 77186a4..733b403 100644
|
||||
--- a/salt/cloud/__init__.py
|
||||
+++ b/salt/cloud/__init__.py
|
||||
@@ -2036,7 +2036,7 @@ class Map(Cloud):
|
||||
master_temp_pub = salt.utils.mkstemp()
|
||||
with salt.utils.fopen(master_temp_pub, 'w') as mtp:
|
||||
mtp.write(pub)
|
||||
- master_finger = salt.utils.pem_finger(master_temp_pub)
|
||||
+ master_finger = salt.utils.pem_finger(master_temp_pub, sum_type=self.opts['hash_type'])
|
||||
os.unlink(master_temp_pub)
|
||||
|
||||
if master_profile.get('make_minion', True) is True:
|
||||
@@ -2121,7 +2121,7 @@ class Map(Cloud):
|
||||
# mitigate man-in-the-middle attacks
|
||||
master_pub = os.path.join(self.opts['pki_dir'], 'master.pub')
|
||||
if os.path.isfile(master_pub):
|
||||
- master_finger = salt.utils.pem_finger(master_pub)
|
||||
+ master_finger = salt.utils.pem_finger(master_pub, sum_type=self.opts['hash_type'])
|
||||
|
||||
opts = self.opts.copy()
|
||||
if self.opts['parallel']:
|
||||
diff --git a/salt/crypt.py b/salt/crypt.py
|
||||
index 907ec0c..eaf6d72 100644
|
||||
--- a/salt/crypt.py
|
||||
+++ b/salt/crypt.py
|
||||
@@ -558,11 +558,11 @@ class AsyncAuth(object):
|
||||
if self.opts.get('syndic_master', False): # Is syndic
|
||||
syndic_finger = self.opts.get('syndic_finger', self.opts.get('master_finger', False))
|
||||
if syndic_finger:
|
||||
- if salt.utils.pem_finger(m_pub_fn) != syndic_finger:
|
||||
+ if salt.utils.pem_finger(m_pub_fn, sum_type=self.opts['hash_type']) != syndic_finger:
|
||||
self._finger_fail(syndic_finger, m_pub_fn)
|
||||
else:
|
||||
if self.opts.get('master_finger', False):
|
||||
- if salt.utils.pem_finger(m_pub_fn) != self.opts['master_finger']:
|
||||
+ if salt.utils.pem_finger(m_pub_fn, sum_type=self.opts['hash_type']) != self.opts['master_finger']:
|
||||
self._finger_fail(self.opts['master_finger'], m_pub_fn)
|
||||
auth['publish_port'] = payload['publish_port']
|
||||
raise tornado.gen.Return(auth)
|
||||
@@ -1071,11 +1071,11 @@ class SAuth(AsyncAuth):
|
||||
if self.opts.get('syndic_master', False): # Is syndic
|
||||
syndic_finger = self.opts.get('syndic_finger', self.opts.get('master_finger', False))
|
||||
if syndic_finger:
|
||||
- if salt.utils.pem_finger(m_pub_fn) != syndic_finger:
|
||||
+ if salt.utils.pem_finger(m_pub_fn, sum_type=self.opts['hash_type']) != syndic_finger:
|
||||
self._finger_fail(syndic_finger, m_pub_fn)
|
||||
else:
|
||||
if self.opts.get('master_finger', False):
|
||||
- if salt.utils.pem_finger(m_pub_fn) != self.opts['master_finger']:
|
||||
+ if salt.utils.pem_finger(m_pub_fn, sum_type=self.opts['hash_type']) != self.opts['master_finger']:
|
||||
self._finger_fail(self.opts['master_finger'], m_pub_fn)
|
||||
auth['publish_port'] = payload['publish_port']
|
||||
return auth
|
||||
@@ -1089,7 +1089,7 @@ class SAuth(AsyncAuth):
|
||||
'this minion is not subject to a man-in-the-middle attack.'
|
||||
.format(
|
||||
finger,
|
||||
- salt.utils.pem_finger(master_key)
|
||||
+ salt.utils.pem_finger(master_key, sum_type=self.opts['hash_type'])
|
||||
)
|
||||
)
|
||||
sys.exit(42)
|
||||
diff --git a/salt/key.py b/salt/key.py
|
||||
index 08086a0..e4cb4eb 100644
|
||||
--- a/salt/key.py
|
||||
+++ b/salt/key.py
|
||||
@@ -933,7 +933,7 @@ class Key(object):
|
||||
path = os.path.join(self.opts['pki_dir'], key)
|
||||
else:
|
||||
path = os.path.join(self.opts['pki_dir'], status, key)
|
||||
- ret[status][key] = salt.utils.pem_finger(path)
|
||||
+ ret[status][key] = salt.utils.pem_finger(path, sum_type=self.opts['hash_type'])
|
||||
return ret
|
||||
|
||||
def finger_all(self):
|
||||
@@ -948,7 +948,7 @@ class Key(object):
|
||||
path = os.path.join(self.opts['pki_dir'], key)
|
||||
else:
|
||||
path = os.path.join(self.opts['pki_dir'], status, key)
|
||||
- ret[status][key] = salt.utils.pem_finger(path)
|
||||
+ ret[status][key] = salt.utils.pem_finger(path, sum_type=self.opts['hash_type'])
|
||||
return ret
|
||||
|
||||
|
||||
diff --git a/salt/modules/key.py b/salt/modules/key.py
|
||||
index 12762df..3e16c2d 100644
|
||||
--- a/salt/modules/key.py
|
||||
+++ b/salt/modules/key.py
|
||||
@@ -21,9 +21,8 @@ def finger():
|
||||
|
||||
salt '*' key.finger
|
||||
'''
|
||||
- return salt.utils.pem_finger(
|
||||
- os.path.join(__opts__['pki_dir'], 'minion.pub')
|
||||
- )
|
||||
+ return salt.utils.pem_finger(os.path.join(__opts__['pki_dir'], 'minion.pub'),
|
||||
+ sum_type=__opts__.get('hash_type', 'md5'))
|
||||
|
||||
|
||||
def finger_master():
|
||||
@@ -36,6 +35,5 @@ def finger_master():
|
||||
|
||||
salt '*' key.finger_master
|
||||
'''
|
||||
- return salt.utils.pem_finger(
|
||||
- os.path.join(__opts__['pki_dir'], 'minion_master.pub')
|
||||
- )
|
||||
+ return salt.utils.pem_finger(os.path.join(__opts__['pki_dir'], 'minion_master.pub'),
|
||||
+ sum_type=__opts__.get('hash_type', 'md5'))
|
||||
diff --git a/salt/modules/tomcat.py b/salt/modules/tomcat.py
|
||||
index d3df2dc..4a7f0eb 100644
|
||||
--- a/salt/modules/tomcat.py
|
||||
+++ b/salt/modules/tomcat.py
|
||||
@@ -610,7 +610,7 @@ def deploy_war(war,
|
||||
|
||||
def passwd(passwd,
|
||||
user='',
|
||||
- alg='md5',
|
||||
+ alg='sha1',
|
||||
realm=None):
|
||||
'''
|
||||
This function replaces the $CATALINA_HOME/bin/digest.sh script
|
||||
@@ -625,23 +625,15 @@ def passwd(passwd,
|
||||
salt '*' tomcat.passwd secret tomcat sha1
|
||||
salt '*' tomcat.passwd secret tomcat sha1 'Protected Realm'
|
||||
'''
|
||||
- if alg == 'md5':
|
||||
- m = hashlib.md5()
|
||||
- elif alg == 'sha1':
|
||||
- m = hashlib.sha1()
|
||||
- else:
|
||||
- return False
|
||||
-
|
||||
- if realm:
|
||||
- m.update('{0}:{1}:{2}'.format(
|
||||
- user,
|
||||
- realm,
|
||||
- passwd,
|
||||
- ))
|
||||
- else:
|
||||
- m.update(passwd)
|
||||
+ # Shouldn't it be SHA265 instead of SHA1?
|
||||
+ digest = hasattr(hashlib, alg) and getattr(hashlib, alg) or None
|
||||
+ if digest:
|
||||
+ if realm:
|
||||
+ digest.update('{0}:{1}:{2}'.format(user, realm, passwd,))
|
||||
+ else:
|
||||
+ digest.update(passwd)
|
||||
|
||||
- return m.hexdigest()
|
||||
+ return digest and digest.hexdigest() or False
|
||||
|
||||
|
||||
# Non-Manager functions
|
||||
diff --git a/salt/modules/win_file.py b/salt/modules/win_file.py
|
||||
index 7911bfc..5ea31ae 100644
|
||||
--- a/salt/modules/win_file.py
|
||||
+++ b/salt/modules/win_file.py
|
||||
@@ -842,7 +842,7 @@ def chgrp(path, group):
|
||||
return None
|
||||
|
||||
|
||||
-def stats(path, hash_type='md5', follow_symlinks=True):
|
||||
+def stats(path, hash_type='sha256', follow_symlinks=True):
|
||||
'''
|
||||
Return a dict containing the stats for a given file
|
||||
|
||||
diff --git a/salt/utils/__init__.py b/salt/utils/__init__.py
|
||||
index c6a3fd3..4e40caf 100644
|
||||
--- a/salt/utils/__init__.py
|
||||
+++ b/salt/utils/__init__.py
|
||||
@@ -858,10 +858,11 @@ def path_join(*parts):
|
||||
))
|
||||
|
||||
|
||||
-def pem_finger(path=None, key=None, sum_type='md5'):
|
||||
+def pem_finger(path=None, key=None, sum_type='sha256'):
|
||||
'''
|
||||
Pass in either a raw pem string, or the path on disk to the location of a
|
||||
- pem file, and the type of cryptographic hash to use. The default is md5.
|
||||
+ pem file, and the type of cryptographic hash to use. The default is SHA256.
|
||||
+
|
||||
The fingerprint of the pem will be returned.
|
||||
|
||||
If neither a key nor a path are passed in, a blank string will be returned.
|
||||
@@ -1979,7 +1980,7 @@ def safe_walk(top, topdown=True, onerror=None, followlinks=True, _seen=None):
|
||||
yield top, dirs, nondirs
|
||||
|
||||
|
||||
-def get_hash(path, form='md5', chunk_size=65536):
|
||||
+def get_hash(path, form='sha256', chunk_size=65536):
|
||||
'''
|
||||
Get the hash sum of a file
|
||||
|
||||
@@ -1989,10 +1990,10 @@ def get_hash(path, form='md5', chunk_size=65536):
|
||||
``get_sum`` cannot really be trusted since it is vulnerable to
|
||||
collisions: ``get_sum(..., 'xyz') == 'Hash xyz not supported'``
|
||||
'''
|
||||
- try:
|
||||
- hash_type = getattr(hashlib, form)
|
||||
- except (AttributeError, TypeError):
|
||||
+ hash_type = hasattr(hashlib, form) and getattr(hashlib, form) or None
|
||||
+ if hash_type is None:
|
||||
raise ValueError('Invalid hash type: {0}'.format(form))
|
||||
+
|
||||
with salt.utils.fopen(path, 'rb') as ifile:
|
||||
hash_obj = hash_type()
|
||||
# read the file in in chunks, not the entire file
|
||||
diff --git a/salt/utils/cloud.py b/salt/utils/cloud.py
|
||||
index d546e51..7a21166 100644
|
||||
--- a/salt/utils/cloud.py
|
||||
+++ b/salt/utils/cloud.py
|
||||
@@ -2421,6 +2421,7 @@ def init_cachedir(base=None):
|
||||
|
||||
def request_minion_cachedir(
|
||||
minion_id,
|
||||
+ opts=None,
|
||||
fingerprint='',
|
||||
pubkey=None,
|
||||
provider=None,
|
||||
@@ -2440,7 +2441,7 @@ def request_minion_cachedir(
|
||||
|
||||
if not fingerprint:
|
||||
if pubkey is not None:
|
||||
- fingerprint = salt.utils.pem_finger(key=pubkey)
|
||||
+ fingerprint = salt.utils.pem_finger(key=pubkey, sum_type=(opts and opts.get('hash_type') or 'sha256'))
|
||||
|
||||
init_cachedir(base)
|
||||
|
||||
diff --git a/tests/unit/daemons_test.py b/tests/unit/daemons_test.py
|
||||
new file mode 100644
|
||||
index 0000000..47d5e8a
|
||||
--- /dev/null
|
||||
+++ b/tests/unit/daemons_test.py
|
||||
@@ -0,0 +1,209 @@
|
||||
+# -*- coding: utf-8 -*-
|
||||
+'''
|
||||
+ :codeauthor: :email:`Bo Maryniuk <bo@suse.de>`
|
||||
+'''
|
||||
+
|
||||
+# Import python libs
|
||||
+from __future__ import absolute_import
|
||||
+
|
||||
+# Import Salt Testing libs
|
||||
+from salttesting import TestCase, skipIf
|
||||
+from salttesting.helpers import ensure_in_syspath
|
||||
+from salttesting.mock import patch, MagicMock, NO_MOCK, NO_MOCK_REASON
|
||||
+
|
||||
+ensure_in_syspath('../')
|
||||
+
|
||||
+# Import Salt libs
|
||||
+import integration
|
||||
+from salt.cli import daemons
|
||||
+
|
||||
+
|
||||
+class LoggerMock(object):
|
||||
+ '''
|
||||
+ Logger data collector
|
||||
+ '''
|
||||
+
|
||||
+ def __init__(self):
|
||||
+ '''
|
||||
+ init
|
||||
+ :return:
|
||||
+ '''
|
||||
+ self.reset()
|
||||
+
|
||||
+ def reset(self):
|
||||
+ '''
|
||||
+ Reset values
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+ self.last_message = self.last_type = None
|
||||
+
|
||||
+ def info(self, data):
|
||||
+ '''
|
||||
+ Collects the data from the logger of info type.
|
||||
+
|
||||
+ :param data:
|
||||
+ :return:
|
||||
+ '''
|
||||
+ self.last_message = data
|
||||
+ self.last_type = 'info'
|
||||
+
|
||||
+ def warning(self, data):
|
||||
+ '''
|
||||
+ Collects the data from the logger of warning type.
|
||||
+
|
||||
+ :param data:
|
||||
+ :return:
|
||||
+ '''
|
||||
+ self.last_message = data
|
||||
+ self.last_type = 'warning'
|
||||
+
|
||||
+
|
||||
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
+class DaemonsStarterTestCase(TestCase, integration.SaltClientTestCaseMixIn):
|
||||
+ '''
|
||||
+ Unit test for the daemons starter classes.
|
||||
+ '''
|
||||
+
|
||||
+ def test_master_daemon_hash_type_verified(self):
|
||||
+ '''
|
||||
+ Verify if Master is verifying hash_type config option.
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+ def _create_master():
|
||||
+ '''
|
||||
+ Create master instance
|
||||
+ :return:
|
||||
+ '''
|
||||
+ master = daemons.Master()
|
||||
+ master.config = {'user': 'dummy', 'hash_type': alg}
|
||||
+ for attr in ['master', 'start_log_info', 'prepare']:
|
||||
+ setattr(master, attr, MagicMock())
|
||||
+
|
||||
+ return master
|
||||
+
|
||||
+ _logger = LoggerMock()
|
||||
+ with patch('salt.cli.daemons.check_user', MagicMock(return_value=True)):
|
||||
+ with patch('salt.cli.daemons.logger', _logger):
|
||||
+ for alg in ['md5', 'sha1']:
|
||||
+ _create_master().start()
|
||||
+ self.assertEqual(_logger.last_type, 'warning')
|
||||
+ self.assertTrue(_logger.last_message)
|
||||
+ self.assertTrue(_logger.last_message.find('Do not use {alg}'.format(alg=alg)) > -1)
|
||||
+
|
||||
+ _logger.reset()
|
||||
+
|
||||
+ for alg in ['sha224', 'sha256', 'sha384', 'sha512']:
|
||||
+ _create_master().start()
|
||||
+ self.assertEqual(_logger.last_type, None)
|
||||
+ self.assertFalse(_logger.last_message)
|
||||
+
|
||||
+ def test_minion_daemon_hash_type_verified(self):
|
||||
+ '''
|
||||
+ Verify if Minion is verifying hash_type config option.
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+
|
||||
+ def _create_minion():
|
||||
+ '''
|
||||
+ Create minion instance
|
||||
+ :return:
|
||||
+ '''
|
||||
+ obj = daemons.Minion()
|
||||
+ obj.config = {'user': 'dummy', 'hash_type': alg}
|
||||
+ for attr in ['minion', 'start_log_info', 'prepare', 'shutdown']:
|
||||
+ setattr(obj, attr, MagicMock())
|
||||
+
|
||||
+ return obj
|
||||
+
|
||||
+ _logger = LoggerMock()
|
||||
+ with patch('salt.cli.daemons.check_user', MagicMock(return_value=True)):
|
||||
+ with patch('salt.cli.daemons.logger', _logger):
|
||||
+ for alg in ['md5', 'sha1']:
|
||||
+ _create_minion().start()
|
||||
+ self.assertEqual(_logger.last_type, 'warning')
|
||||
+ self.assertTrue(_logger.last_message)
|
||||
+ self.assertTrue(_logger.last_message.find('Do not use {alg}'.format(alg=alg)) > -1)
|
||||
+
|
||||
+ _logger.reset()
|
||||
+
|
||||
+ for alg in ['sha224', 'sha256', 'sha384', 'sha512']:
|
||||
+ _create_minion().start()
|
||||
+ self.assertEqual(_logger.last_type, None)
|
||||
+ self.assertFalse(_logger.last_message)
|
||||
+
|
||||
+ def test_proxy_minion_daemon_hash_type_verified(self):
|
||||
+ '''
|
||||
+ Verify if ProxyMinion is verifying hash_type config option.
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+
|
||||
+ def _create_proxy_minion():
|
||||
+ '''
|
||||
+ Create proxy minion instance
|
||||
+ :return:
|
||||
+ '''
|
||||
+ obj = daemons.ProxyMinion()
|
||||
+ obj.config = {'user': 'dummy', 'hash_type': alg}
|
||||
+ for attr in ['minion', 'start_log_info', 'prepare', 'shutdown']:
|
||||
+ setattr(obj, attr, MagicMock())
|
||||
+
|
||||
+ return obj
|
||||
+
|
||||
+ _logger = LoggerMock()
|
||||
+ with patch('salt.cli.daemons.check_user', MagicMock(return_value=True)):
|
||||
+ with patch('salt.cli.daemons.logger', _logger):
|
||||
+ for alg in ['md5', 'sha1']:
|
||||
+ _create_proxy_minion().start()
|
||||
+ self.assertEqual(_logger.last_type, 'warning')
|
||||
+ self.assertTrue(_logger.last_message)
|
||||
+ self.assertTrue(_logger.last_message.find('Do not use {alg}'.format(alg=alg)) > -1)
|
||||
+
|
||||
+ _logger.reset()
|
||||
+
|
||||
+ for alg in ['sha224', 'sha256', 'sha384', 'sha512']:
|
||||
+ _create_proxy_minion().start()
|
||||
+ self.assertEqual(_logger.last_type, None)
|
||||
+ self.assertFalse(_logger.last_message)
|
||||
+
|
||||
+ def test_syndic_daemon_hash_type_verified(self):
|
||||
+ '''
|
||||
+ Verify if Syndic is verifying hash_type config option.
|
||||
+
|
||||
+ :return:
|
||||
+ '''
|
||||
+
|
||||
+ def _create_syndic():
|
||||
+ '''
|
||||
+ Create syndic instance
|
||||
+ :return:
|
||||
+ '''
|
||||
+ obj = daemons.Syndic()
|
||||
+ obj.config = {'user': 'dummy', 'hash_type': alg}
|
||||
+ for attr in ['syndic', 'start_log_info', 'prepare', 'shutdown']:
|
||||
+ setattr(obj, attr, MagicMock())
|
||||
+
|
||||
+ return obj
|
||||
+
|
||||
+ _logger = LoggerMock()
|
||||
+ with patch('salt.cli.daemons.check_user', MagicMock(return_value=True)):
|
||||
+ with patch('salt.cli.daemons.logger', _logger):
|
||||
+ for alg in ['md5', 'sha1']:
|
||||
+ _create_syndic().start()
|
||||
+ self.assertEqual(_logger.last_type, 'warning')
|
||||
+ self.assertTrue(_logger.last_message)
|
||||
+ self.assertTrue(_logger.last_message.find('Do not use {alg}'.format(alg=alg)) > -1)
|
||||
+
|
||||
+ _logger.reset()
|
||||
+
|
||||
+ for alg in ['sha224', 'sha256', 'sha384', 'sha512']:
|
||||
+ _create_syndic().start()
|
||||
+ self.assertEqual(_logger.last_type, None)
|
||||
+ self.assertFalse(_logger.last_message)
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ from integration import run_tests
|
||||
+ run_tests(DaemonsStarterTestCase, needs_daemon=False)
|
||||
--
|
||||
2.7.2
|
||||
|
228
0030-Bugfix-on-SLE11-series-base-product-reported-as-addi.patch
Normal file
228
0030-Bugfix-on-SLE11-series-base-product-reported-as-addi.patch
Normal file
@ -0,0 +1,228 @@
|
||||
From 79d5477cfa5e85d2480bb07e49ecaeff423f5238 Mon Sep 17 00:00:00 2001
|
||||
From: Bo Maryniuk <bo@suse.de>
|
||||
Date: Thu, 10 Mar 2016 13:25:20 +0100
|
||||
Subject: [PATCH 30/33] Bugfix: on SLE11 series base product reported as
|
||||
additional
|
||||
|
||||
Add SLE11 product info snapshot, rename previous
|
||||
|
||||
Update test case to cover SLE11 and SLE12
|
||||
---
|
||||
salt/modules/zypper.py | 2 +-
|
||||
.../unit/modules/zypp/zypper-products-sle11sp3.xml | 37 +++++++++++++++
|
||||
.../unit/modules/zypp/zypper-products-sle12sp1.xml | 37 +++++++++++++++
|
||||
tests/unit/modules/zypp/zypper-products.xml | 37 ---------------
|
||||
tests/unit/modules/zypper_test.py | 52 +++++++++++++---------
|
||||
5 files changed, 107 insertions(+), 58 deletions(-)
|
||||
create mode 100644 tests/unit/modules/zypp/zypper-products-sle11sp3.xml
|
||||
create mode 100644 tests/unit/modules/zypp/zypper-products-sle12sp1.xml
|
||||
delete mode 100644 tests/unit/modules/zypp/zypper-products.xml
|
||||
|
||||
diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py
|
||||
index d6628aa..1c6b31d 100644
|
||||
--- a/salt/modules/zypper.py
|
||||
+++ b/salt/modules/zypper.py
|
||||
@@ -1373,7 +1373,7 @@ def list_products(all=False, refresh=False):
|
||||
for prd in doc.getElementsByTagName('product-list')[0].getElementsByTagName('product'):
|
||||
p_nfo = dict()
|
||||
for k_p_nfo, v_p_nfo in prd.attributes.items():
|
||||
- p_nfo[k_p_nfo] = k_p_nfo not in ['isbase', 'installed'] and v_p_nfo or v_p_nfo == 'true'
|
||||
+ p_nfo[k_p_nfo] = k_p_nfo not in ['isbase', 'installed'] and v_p_nfo or v_p_nfo in ['true', '1']
|
||||
p_nfo['eol'] = prd.getElementsByTagName('endoflife')[0].getAttribute('text')
|
||||
p_nfo['eol_t'] = int(prd.getElementsByTagName('endoflife')[0].getAttribute('time_t'))
|
||||
p_nfo['description'] = " ".join(
|
||||
diff --git a/tests/unit/modules/zypp/zypper-products-sle11sp3.xml b/tests/unit/modules/zypp/zypper-products-sle11sp3.xml
|
||||
new file mode 100644
|
||||
index 0000000..89a85e3
|
||||
--- /dev/null
|
||||
+++ b/tests/unit/modules/zypp/zypper-products-sle11sp3.xml
|
||||
@@ -0,0 +1,37 @@
|
||||
+<?xml version='1.0'?>
|
||||
+<stream>
|
||||
+<message type="info">Refreshing service 'nu_novell_com'.</message>
|
||||
+<message type="info">Loading repository data...</message>
|
||||
+<message type="info">Reading installed packages...</message>
|
||||
+<product-list>
|
||||
+<product name="SUSE_SLES" version="11.3" release="1.138" epoch="0" arch="x86_64" productline="" registerrelease="" vendor="SUSE LINUX Products GmbH, Nuernberg, Germany" summary="SUSE Linux Enterprise Server 11 SP3" shortname="" flavor="" isbase="0" repo="nu_novell_com:SLES11-SP3-Pool" installed="0"><endoflife time_t="0" text="1970-01-01T01:00:00+0100"/>0x7ffdb538e948<description>SUSE Linux Enterprise offers a comprehensive
|
||||
+ suite of products built on a single code base.
|
||||
+ The platform addresses business needs from
|
||||
+ the smallest thin-client devices to the world’s
|
||||
+ most powerful high-performance computing
|
||||
+ and mainframe servers. SUSE Linux Enterprise
|
||||
+ offers common management tools and technology
|
||||
+ certifications across the platform, and
|
||||
+ each product is enterprise-class.</description></product>
|
||||
+<product name="SUSE_SLES-SP4-migration" version="11.3" release="1.4" epoch="0" arch="x86_64" productline="" registerrelease="" vendor="SUSE LINUX Products GmbH, Nuernberg, Germany" summary="SUSE_SLES Service Pack 4 Migration Product" shortname="" flavor="" isbase="0" repo="nu_novell_com:SLES11-SP3-Updates" installed="0"><endoflife time_t="0" text="1970-01-01T01:00:00+0100"/>0x7ffdb538e948<description>SUSE Linux Enterprise offers a comprehensive
|
||||
+ suite of products built on a single code base.
|
||||
+ The platform addresses business needs from
|
||||
+ the smallest thin-client devices to the world’s
|
||||
+ most powerful high-performance computing
|
||||
+ and mainframe servers. SUSE Linux Enterprise
|
||||
+ offers common management tools and technology
|
||||
+ certifications across the platform, and
|
||||
+ each product is enterprise-class.</description></product>
|
||||
+<product name="SUSE_SLES" version="11.3" release="1.201" epoch="0" arch="x86_64" productline="" registerrelease="" vendor="SUSE LINUX Products GmbH, Nuernberg, Germany" summary="SUSE Linux Enterprise Server 11 SP3" shortname="" flavor="" isbase="0" repo="nu_novell_com:SLES11-SP3-Updates" installed="0"><endoflife time_t="0" text="1970-01-01T01:00:00+0100"/>0x7ffdb538e948<description>SUSE Linux Enterprise offers a comprehensive
|
||||
+ suite of products built on a single code base.
|
||||
+ The platform addresses business needs from
|
||||
+ the smallest thin-client devices to the world’s
|
||||
+ most powerful high-performance computing
|
||||
+ and mainframe servers. SUSE Linux Enterprise
|
||||
+ offers common management tools and technology
|
||||
+ certifications across the platform, and
|
||||
+ each product is enterprise-class.</description></product>
|
||||
+<product name="SUSE-Manager-Server" version="2.1" release="1.2" epoch="0" arch="x86_64" productline="" registerrelease="" vendor="SUSE LINUX Products GmbH, Nuernberg, Germany" summary="SUSE Manager Server" shortname="" flavor="cd" isbase="0" repo="nu_novell_com:SUSE-Manager-Server-2.1-Pool" installed="0"><endoflife time_t="0" text="1970-01-01T01:00:00+0100"/>0x7ffdb538e948<description>SUSE Manager Server appliance</description></product>
|
||||
+<product name="SUSE-Manager-Server" version="2.1" release="1.2" epoch="0" arch="x86_64" productline="manager" registerrelease="" vendor="SUSE LINUX Products GmbH, Nuernberg, Germany" summary="SUSE Manager Server" shortname="" flavor="cd" isbase="1" repo="@System" installed="1"><endoflife time_t="0" text="1970-01-01T01:00:00+0100"/>0x7ffdb538e948<description>SUSE Manager Server appliance</description></product>
|
||||
+</product-list>
|
||||
+</stream>
|
||||
diff --git a/tests/unit/modules/zypp/zypper-products-sle12sp1.xml b/tests/unit/modules/zypp/zypper-products-sle12sp1.xml
|
||||
new file mode 100644
|
||||
index 0000000..1a50363
|
||||
--- /dev/null
|
||||
+++ b/tests/unit/modules/zypp/zypper-products-sle12sp1.xml
|
||||
@@ -0,0 +1,37 @@
|
||||
+<?xml version='1.0'?>
|
||||
+<stream>
|
||||
+<message type="info">Loading repository data...</message>
|
||||
+<message type="info">Reading installed packages...</message>
|
||||
+<product-list>
|
||||
+<product name="SLES" version="12.1" release="0" epoch="0" arch="x86_64" vendor="SUSE LLC <https://www.suse.com/>" summary="SUSE Linux Enterprise Server 12 SP1" repo="SLE12-SP1-x86_64-Pool" productline="" registerrelease="" shortname="SLES12-SP1" flavor="POOL" isbase="false" installed="false"><endoflife time_t="1730332800" text="2024-10-31T01:00:00+01"/><registerflavor/><description>SUSE Linux Enterprise offers a comprehensive
|
||||
+ suite of products built on a single code base.
|
||||
+ The platform addresses business needs from
|
||||
+ the smallest thin-client devices to the world's
|
||||
+ most powerful high-performance computing
|
||||
+ and mainframe servers. SUSE Linux Enterprise
|
||||
+ offers common management tools and technology
|
||||
+ certifications across the platform, and
|
||||
+ each product is enterprise-class.</description></product>
|
||||
+<product name="SUSE-Manager-Proxy" version="3.0" release="0" epoch="0" arch="x86_64" vendor="obs://build.suse.de/Devel:Galaxy:Manager:Head" summary="SUSE Manager Proxy" repo="SUSE-Manager-Head" productline="" registerrelease="" shortname="SUSE Manager Proxy" flavor="DVD" isbase="false" installed="false"><endoflife time_t="1522454400" text="2018-03-31T02:00:00+02"/><registerflavor>extension</registerflavor><description>SUSE Manager Proxies extend large and/or geographically
|
||||
+dispersed SUSE Manager environments to reduce load on the SUSE Manager
|
||||
+Server, lower bandwidth needs, and provide faster local
|
||||
+updates.</description></product>
|
||||
+<product name="SUSE-Manager-Server" version="3.0" release="0" epoch="0" arch="x86_64" vendor="obs://build.suse.de/Devel:Galaxy:Manager:Head" summary="SUSE Manager Server" repo="SUSE-Manager-Head" productline="" registerrelease="" shortname="SUSE Manager Server" flavor="DVD" isbase="false" installed="false"><endoflife time_t="1522454400" text="2018-03-31T02:00:00+02"/><registerflavor>extension</registerflavor><description>SUSE Manager lets you efficiently manage physical, virtual,
|
||||
+and cloud-based Linux systems. It provides automated and cost-effective
|
||||
+configuration and software management, asset management, and system
|
||||
+provisioning.</description></product>
|
||||
+<product name="sle-manager-tools-beta" version="12" release="0" epoch="0" arch="x86_64" vendor="obs://build.suse.de/Devel:Galaxy:Manager:Head" summary="SUSE Manager Tools" repo="SUSE-Manager-Head" productline="" registerrelease="" shortname="Manager-Tools" flavor="POOL" isbase="false" installed="false"><endoflife time_t="1509408000" text="2017-10-31T01:00:00+01"/><registerflavor>extension</registerflavor><description><p>
|
||||
+ SUSE Manager Tools provide packages required to connect to a
|
||||
+ SUSE Manager Server.
|
||||
+ <p></description></product>
|
||||
+<product name="SLES" version="12.1" release="0" epoch="0" arch="x86_64" vendor="SUSE" summary="SUSE Linux Enterprise Server 12 SP1" repo="@System" productline="sles" registerrelease="" shortname="SLES12-SP1" flavor="DVD" isbase="true" installed="true"><endoflife time_t="1730332800" text="2024-10-31T01:00:00+01"/><registerflavor/><description>SUSE Linux Enterprise offers a comprehensive
|
||||
+ suite of products built on a single code base.
|
||||
+ The platform addresses business needs from
|
||||
+ the smallest thin-client devices to the world's
|
||||
+ most powerful high-performance computing
|
||||
+ and mainframe servers. SUSE Linux Enterprise
|
||||
+ offers common management tools and technology
|
||||
+ certifications across the platform, and
|
||||
+ each product is enterprise-class.</description></product>
|
||||
+</product-list>
|
||||
+</stream>
|
||||
diff --git a/tests/unit/modules/zypp/zypper-products.xml b/tests/unit/modules/zypp/zypper-products.xml
|
||||
deleted file mode 100644
|
||||
index 1a50363..0000000
|
||||
--- a/tests/unit/modules/zypp/zypper-products.xml
|
||||
+++ /dev/null
|
||||
@@ -1,37 +0,0 @@
|
||||
-<?xml version='1.0'?>
|
||||
-<stream>
|
||||
-<message type="info">Loading repository data...</message>
|
||||
-<message type="info">Reading installed packages...</message>
|
||||
-<product-list>
|
||||
-<product name="SLES" version="12.1" release="0" epoch="0" arch="x86_64" vendor="SUSE LLC <https://www.suse.com/>" summary="SUSE Linux Enterprise Server 12 SP1" repo="SLE12-SP1-x86_64-Pool" productline="" registerrelease="" shortname="SLES12-SP1" flavor="POOL" isbase="false" installed="false"><endoflife time_t="1730332800" text="2024-10-31T01:00:00+01"/><registerflavor/><description>SUSE Linux Enterprise offers a comprehensive
|
||||
- suite of products built on a single code base.
|
||||
- The platform addresses business needs from
|
||||
- the smallest thin-client devices to the world's
|
||||
- most powerful high-performance computing
|
||||
- and mainframe servers. SUSE Linux Enterprise
|
||||
- offers common management tools and technology
|
||||
- certifications across the platform, and
|
||||
- each product is enterprise-class.</description></product>
|
||||
-<product name="SUSE-Manager-Proxy" version="3.0" release="0" epoch="0" arch="x86_64" vendor="obs://build.suse.de/Devel:Galaxy:Manager:Head" summary="SUSE Manager Proxy" repo="SUSE-Manager-Head" productline="" registerrelease="" shortname="SUSE Manager Proxy" flavor="DVD" isbase="false" installed="false"><endoflife time_t="1522454400" text="2018-03-31T02:00:00+02"/><registerflavor>extension</registerflavor><description>SUSE Manager Proxies extend large and/or geographically
|
||||
-dispersed SUSE Manager environments to reduce load on the SUSE Manager
|
||||
-Server, lower bandwidth needs, and provide faster local
|
||||
-updates.</description></product>
|
||||
-<product name="SUSE-Manager-Server" version="3.0" release="0" epoch="0" arch="x86_64" vendor="obs://build.suse.de/Devel:Galaxy:Manager:Head" summary="SUSE Manager Server" repo="SUSE-Manager-Head" productline="" registerrelease="" shortname="SUSE Manager Server" flavor="DVD" isbase="false" installed="false"><endoflife time_t="1522454400" text="2018-03-31T02:00:00+02"/><registerflavor>extension</registerflavor><description>SUSE Manager lets you efficiently manage physical, virtual,
|
||||
-and cloud-based Linux systems. It provides automated and cost-effective
|
||||
-configuration and software management, asset management, and system
|
||||
-provisioning.</description></product>
|
||||
-<product name="sle-manager-tools-beta" version="12" release="0" epoch="0" arch="x86_64" vendor="obs://build.suse.de/Devel:Galaxy:Manager:Head" summary="SUSE Manager Tools" repo="SUSE-Manager-Head" productline="" registerrelease="" shortname="Manager-Tools" flavor="POOL" isbase="false" installed="false"><endoflife time_t="1509408000" text="2017-10-31T01:00:00+01"/><registerflavor>extension</registerflavor><description><p>
|
||||
- SUSE Manager Tools provide packages required to connect to a
|
||||
- SUSE Manager Server.
|
||||
- <p></description></product>
|
||||
-<product name="SLES" version="12.1" release="0" epoch="0" arch="x86_64" vendor="SUSE" summary="SUSE Linux Enterprise Server 12 SP1" repo="@System" productline="sles" registerrelease="" shortname="SLES12-SP1" flavor="DVD" isbase="true" installed="true"><endoflife time_t="1730332800" text="2024-10-31T01:00:00+01"/><registerflavor/><description>SUSE Linux Enterprise offers a comprehensive
|
||||
- suite of products built on a single code base.
|
||||
- The platform addresses business needs from
|
||||
- the smallest thin-client devices to the world's
|
||||
- most powerful high-performance computing
|
||||
- and mainframe servers. SUSE Linux Enterprise
|
||||
- offers common management tools and technology
|
||||
- certifications across the platform, and
|
||||
- each product is enterprise-class.</description></product>
|
||||
-</product-list>
|
||||
-</stream>
|
||||
diff --git a/tests/unit/modules/zypper_test.py b/tests/unit/modules/zypper_test.py
|
||||
index f89d18f..5c4eb67 100644
|
||||
--- a/tests/unit/modules/zypper_test.py
|
||||
+++ b/tests/unit/modules/zypper_test.py
|
||||
@@ -150,26 +150,38 @@ class ZypperTestCase(TestCase):
|
||||
'''
|
||||
List products test.
|
||||
'''
|
||||
- ref_out = {
|
||||
- 'retcode': 0,
|
||||
- 'stdout': get_test_data('zypper-products.xml')
|
||||
- }
|
||||
- with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
|
||||
- products = zypper.list_products()
|
||||
- self.assertEqual(len(products), 5)
|
||||
- self.assertEqual(['SLES', 'SLES', 'SUSE-Manager-Proxy', 'SUSE-Manager-Server', 'sle-manager-tools-beta'],
|
||||
- sorted([prod['name'] for prod in products]))
|
||||
- self.assertIn('SUSE LLC <https://www.suse.com/>', [product['vendor'] for product in products])
|
||||
- self.assertEqual([False, False, False, False, True],
|
||||
- sorted([product['isbase'] for product in products]))
|
||||
- self.assertEqual([False, False, False, False, True],
|
||||
- sorted([product['installed'] for product in products]))
|
||||
- self.assertEqual(['0', '0', '0', '0', '0'],
|
||||
- sorted([product['release'] for product in products]))
|
||||
- self.assertEqual([False, False, False, False, u'sles'],
|
||||
- sorted([product['productline'] for product in products]))
|
||||
- self.assertEqual([1509408000, 1522454400, 1522454400, 1730332800, 1730332800],
|
||||
- sorted([product['eol_t'] for product in products]))
|
||||
+ for filename, test_data in {
|
||||
+ 'zypper-products-sle12sp1.xml': {
|
||||
+ 'name': ['SLES', 'SLES', 'SUSE-Manager-Proxy',
|
||||
+ 'SUSE-Manager-Server', 'sle-manager-tools-beta'],
|
||||
+ 'vendor': 'SUSE LLC <https://www.suse.com/>',
|
||||
+ 'release': ['0', '0', '0', '0', '0'],
|
||||
+ 'productline': [False, False, False, False, 'sles'],
|
||||
+ 'eol_t': [1509408000, 1522454400, 1522454400, 1730332800, 1730332800],
|
||||
+ 'isbase': [False, False, False, False, True],
|
||||
+ 'installed': [False, False, False, False, True],
|
||||
+ },
|
||||
+ 'zypper-products-sle11sp3.xml': {
|
||||
+ 'name': ['SUSE-Manager-Server', 'SUSE-Manager-Server',
|
||||
+ 'SUSE_SLES', 'SUSE_SLES', 'SUSE_SLES-SP4-migration'],
|
||||
+ 'vendor': 'SUSE LINUX Products GmbH, Nuernberg, Germany',
|
||||
+ 'release': ['1.138', '1.2', '1.2', '1.201', '1.4'],
|
||||
+ 'productline': [False, False, False, False, 'manager'],
|
||||
+ 'eol_t': [0, 0, 0, 0, 0],
|
||||
+ 'isbase': [False, False, False, False, True],
|
||||
+ 'installed': [False, False, False, False, True],
|
||||
+ }}.items():
|
||||
+ ref_out = {
|
||||
+ 'retcode': 0,
|
||||
+ 'stdout': get_test_data(filename)
|
||||
+ }
|
||||
+
|
||||
+ with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
|
||||
+ products = zypper.list_products()
|
||||
+ self.assertEqual(len(products), 5)
|
||||
+ self.assertIn(test_data['vendor'], [product['vendor'] for product in products])
|
||||
+ for kwd in ['name', 'isbase', 'installed', 'release', 'productline', 'eol_t']:
|
||||
+ self.assertEqual(test_data[kwd], sorted([prod[kwd] for prod in products]))
|
||||
|
||||
def test_refresh_db(self):
|
||||
'''
|
||||
--
|
||||
2.1.4
|
||||
|
@ -0,0 +1,42 @@
|
||||
From d3d7d20b569ad1ae5bc8a7ba1ac6652aa2e47ec5 Mon Sep 17 00:00:00 2001
|
||||
From: rallytime <nicole@saltstack.com>
|
||||
Date: Tue, 23 Feb 2016 17:20:47 -0700
|
||||
Subject: [PATCH 31/33] Only use LONGSIZE in rpm.info if available. Otherwise,
|
||||
use SIZE.
|
||||
|
||||
Fixes #31366
|
||||
---
|
||||
salt/modules/rpm.py | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py
|
||||
index 51c72c9..cdf91a6 100644
|
||||
--- a/salt/modules/rpm.py
|
||||
+++ b/salt/modules/rpm.py
|
||||
@@ -422,6 +422,14 @@ def info(*packages, **attr):
|
||||
salt '*' lowpkg.info apache2 bash attr=version
|
||||
salt '*' lowpkg.info apache2 bash attr=version,build_date_iso,size
|
||||
'''
|
||||
+ # LONGSIZE is not a valid tag for all versions of rpm. If LONGSIZE isn't
|
||||
+ # available, then we can just use SIZE for older versions. See Issue #31366.
|
||||
+ rpm_tags = __salt__['cmd.run_all']('rpm --querytags')
|
||||
+ rpm_tags = rpm_tags.get('stdout').split('\n')
|
||||
+ if 'LONGSIZE' in rpm_tags:
|
||||
+ size_tag = '%{LONGSIZE}'
|
||||
+ else:
|
||||
+ size_tag = '%{SIZE}'
|
||||
|
||||
cmd = packages and "rpm -q {0}".format(' '.join(packages)) or "rpm -qa"
|
||||
|
||||
@@ -440,7 +448,7 @@ def info(*packages, **attr):
|
||||
"build_host": "build_host: %{BUILDHOST}\\n",
|
||||
"group": "group: %{GROUP}\\n",
|
||||
"source_rpm": "source_rpm: %{SOURCERPM}\\n",
|
||||
- "size": "size: %{LONGSIZE}\\n",
|
||||
+ "size": "size: " + size_tag + "\\n",
|
||||
"arch": "arch: %{ARCH}\\n",
|
||||
"license": "%|LICENSE?{license: %{LICENSE}\\n}|",
|
||||
"signature": "signature: %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:"
|
||||
--
|
||||
2.1.4
|
||||
|
@ -0,0 +1,26 @@
|
||||
From 5c0c3da01e3e64e7614d9d3cc52d8d9c18a06230 Mon Sep 17 00:00:00 2001
|
||||
From: rallytime <nicole@saltstack.com>
|
||||
Date: Tue, 23 Feb 2016 17:26:52 -0700
|
||||
Subject: [PATCH 32/33] Add error check when retcode is 0, but stderr is
|
||||
present
|
||||
|
||||
---
|
||||
salt/modules/rpm.py | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py
|
||||
index cdf91a6..00cbd5d 100644
|
||||
--- a/salt/modules/rpm.py
|
||||
+++ b/salt/modules/rpm.py
|
||||
@@ -485,6 +485,8 @@ def info(*packages, **attr):
|
||||
if 'stderr' in call:
|
||||
comment += (call['stderr'] or call['stdout'])
|
||||
raise CommandExecutionError('{0}'.format(comment))
|
||||
+ elif 'error' in call['stderr']:
|
||||
+ raise CommandExecutionError(call['stderr'])
|
||||
else:
|
||||
out = call['stdout']
|
||||
|
||||
--
|
||||
2.1.4
|
||||
|
@ -0,0 +1,39 @@
|
||||
From ba08f6714222622467215c23c8284f992830e047 Mon Sep 17 00:00:00 2001
|
||||
From: Richard McIntosh <richard.c.mcintosh@gmail.com>
|
||||
Date: Thu, 10 Mar 2016 16:46:14 +0100
|
||||
Subject: [PATCH 33/33] fixing init system dectection on sles 11, refs #31617
|
||||
|
||||
---
|
||||
salt/modules/rh_service.py | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/salt/modules/rh_service.py b/salt/modules/rh_service.py
|
||||
index 910a75d..c8ebb52 100644
|
||||
--- a/salt/modules/rh_service.py
|
||||
+++ b/salt/modules/rh_service.py
|
||||
@@ -60,14 +60,19 @@ def __virtual__():
|
||||
if __grains__['os'] in enable:
|
||||
if __grains__['os'] == 'XenServer':
|
||||
return __virtualname__
|
||||
+
|
||||
+ if __grains__['os'] == 'SUSE':
|
||||
+ if str(__grains__['osrelease']).startswith('11'):
|
||||
+ return __virtualname__
|
||||
+ else:
|
||||
+ return (False, 'Cannot load rh_service module on SUSE > 11')
|
||||
+
|
||||
try:
|
||||
osrelease = float(__grains__.get('osrelease', 0))
|
||||
except ValueError:
|
||||
return (False, 'Cannot load rh_service module: '
|
||||
'osrelease grain, {0}, not a float,'.format(osrelease))
|
||||
- if __grains__['os'] == 'SUSE':
|
||||
- if osrelease >= 12:
|
||||
- return (False, 'Cannot load rh_service module on SUSE >= 12')
|
||||
+
|
||||
if __grains__['os'] == 'Fedora':
|
||||
if osrelease > 15:
|
||||
return (False, 'Cannot load rh_service module on Fedora >= 15')
|
||||
--
|
||||
2.1.4
|
||||
|
25
salt.changes
25
salt.changes
@ -1,3 +1,28 @@
|
||||
-------------------------------------------------------------------
|
||||
Sat Mar 12 17:08:03 UTC 2016 - mc@suse.com
|
||||
|
||||
- fix detection of base products in SLE11
|
||||
* 0030-Bugfix-on-SLE11-series-base-product-reported-as-addi.patch
|
||||
- fix rpm info for SLE11
|
||||
* 0031-Only-use-LONGSIZE-in-rpm.info-if-available.-Otherwis.patch
|
||||
* 0032-Add-error-check-when-retcode-is-0-but-stderr-is-pres.patch
|
||||
- fix init system detection for SLE11
|
||||
* 0033-fixing-init-system-dectection-on-sles-11-refs-31617.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Mar 11 14:42:52 UTC 2016 - bmaryniuk@suse.com
|
||||
|
||||
- Re-add corrected patch:
|
||||
0029-Make-use-of-checksum-configurable-defaults-to-MD5-SH.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Mar 9 09:39:09 UTC 2016 - kkaempf@suse.com
|
||||
|
||||
- Make checksum configurable (upstream still wants md5, we
|
||||
suggest sha256). bsc#955373
|
||||
Add:
|
||||
0029-Make-use-of-checksum-configurable-defaults-to-MD5-SH.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Mar 4 10:41:52 UTC 2016 - tampakrap@opensuse.org
|
||||
|
||||
|
14
salt.spec
14
salt.spec
@ -96,6 +96,15 @@ Patch26: 0026-do-not-generate-a-date-in-a-comment-to-prevent-rebui.patch
|
||||
# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31629
|
||||
Patch27: 0027-make-suse-check-consistent-with-rh_service.patch
|
||||
Patch28: 0028-fix-numerical-check-of-osrelease.patch
|
||||
# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31162
|
||||
Patch29: 0029-Make-use-of-checksum-configurable-defaults-to-MD5-SH.patch
|
||||
# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31786
|
||||
Patch30: 0030-Bugfix-on-SLE11-series-base-product-reported-as-addi.patch
|
||||
# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31445
|
||||
Patch31: 0031-Only-use-LONGSIZE-in-rpm.info-if-available.-Otherwis.patch
|
||||
Patch32: 0032-Add-error-check-when-retcode-is-0-but-stderr-is-pres.patch
|
||||
# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31793
|
||||
Patch33: 0033-fixing-init-system-dectection-on-sles-11-refs-31617.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildRequires: logrotate
|
||||
@ -466,6 +475,11 @@ cp %{S:1} .
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
|
||||
%build
|
||||
python setup.py --salt-transport=both build
|
||||
|
Loading…
Reference in New Issue
Block a user