Hello community,

here is the log from the commit of package salt for openSUSE:Factory checked in 
at 2018-09-26 14:53:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/salt (Old)
 and      /work/SRC/openSUSE:Factory/.salt.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "salt"

Wed Sep 26 14:53:15 2018 rev:80 rq:636408 version:2018.3.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/salt/salt.changes        2018-08-02 
14:55:43.928034731 +0200
+++ /work/SRC/openSUSE:Factory/.salt.new/salt.changes   2018-09-26 
14:53:17.955118391 +0200
@@ -1,0 +2,53 @@
+Tue Sep 18 14:28:13 UTC 2018 - mihai.di...@suse.com
+
+- Decode file contents for python2 (bsc#1103530)
+- Check dmidecoder executable on each "smbios" call to avoid race condition 
(bsc#1101880)
+- Fix pkg.upgrade reports when dealing with multiversion packages (bsc#1102265)
+- Accounting for when files in an archive contain non-ascii characters 
(bsc#1099460)
+- Fix deprecation warning (bsc#1095507)
+- Fix (bsc#1065792)
+- Fix (bsc#108758)
+- Handle packages with multiple version properly with zypper (bsc#1096514)
+- Fix file.get_diff regression in 2018.3 (bsc#1098394)
+- Provide python version mismatch solutions (bsc#1072599)
+- Fix file.managed binary file utf8 error (bsc#1098394)
+- Prevent zypper from parsing repo configuration from not .repo files 
(bsc#1094055)
+- Add environment variable to know if yum is invoked from Salt (bsc#1057635)
+- Prevent deprecation warning with salt-ssh (bsc#1095507)
+- Align SUSE salt-master.service 'LimitNOFILES' limit with upstream Salt
+- Add 'other' attribute to GECOS fields to avoid inconsistencies with chfn
+- Collect all versions of installed packages on SUSE and RHEL systems 
(bsc#1089526)
+
+-------------------------------------------------------------------
+Mon Sep 17 13:47:09 UTC 2018 - b...@suse.de
+
+- Prepend current directory when path is just filename (bsc#1095942)
+- Integration of MSI authentication for azurearm
+- Adds fix for SUSE Expanded Support os grain detection
+- Fixes 509x remote signing
+- Fix for StringIO import in Python2
+- Use Adler32 algorithm to compute string checksums (bsc#1102819)
+- Only do reverse DNS lookup on IPs for salt-ssh (bsc#1104154)
+- Add support for Python 3.7
+- Fix license macro to build on SLE12SP2
+- Decode file contents for python2 (bsc#1102013)
+- Fix for sorting of multi-version packages (bsc#1097174 and bsc#1097413)
+- Fix mine.get not returning data - workaround for #48020 (bsc#1100142)
+
+- Added:
+  * change-stringio-import-in-python2-to-import-the-clas.patch
+  * integration-of-msi-authentication-with-azurearm-clou.patch
+  * x509-fixes-for-remote-signing-106.patch
+  * fix-for-suse-expanded-support-detection.patch
+  * only-do-reverse-dns-lookup-on-ips-for-salt-ssh.patch
+  * prepend-current-directory-when-path-is-just-filename.patch
+  * add-support-for-python-3.7.patch
+  * decode-file-contents-for-python2-bsc-1102013.patch
+  * fix-mine.get-not-returning-data-workaround-for-48020.patch
+  * x509-fixes-111.patch
+  * use-adler32-algorithm-to-compute-string-checksums.patch
+
+- Modified:
+  * fix-for-sorting-of-multi-version-packages-bsc-109717.patch
+
+-------------------------------------------------------------------
@@ -57 +110 @@
-Thu May 17 15:14:01 UTC 2018 - Jochen Breuer <jbre...@suse.de>
+Thu May 17 15:14:01 UTC 2018 - jbre...@suse.de
@@ -63 +116 @@
-Wed May 16 10:57:17 UTC 2018 - Jochen Breuer <jbre...@suse.de>
+Wed May 16 10:57:17 UTC 2018 - jbre...@suse.de
@@ -73 +126 @@
-Thu May 10 09:12:24 UTC 2018 - Pablo Suárez Hernández 
<psuarezhernan...@suse.com>
+Thu May 10 09:12:24 UTC 2018 - psuarezhernan...@suse.com
@@ -89 +142 @@
-Fri May 4 12:17:07 UTC 2018 - Jochen Breuer <jbre...@suse.de>
+Fri May  4 12:17:07 UTC 2018 - jbre...@suse.de
@@ -97 +150 @@
-Wed Apr 25 14:50:36 UTC 2018 - Pablo Suárez Hernández 
<psuarezhernan...@suse.com>
+Wed Apr 25 14:50:36 UTC 2018 - psuarezhernan...@suse.com
@@ -110 +163 @@
-Wed Apr 18 17:09:41 UTC 2018 - Pablo Suárez Hernández 
<psuarezhernan...@suse.com>
+Wed Apr 18 17:09:41 UTC 2018 - psuarezhernan...@suse.com
@@ -118 +171 @@
-Wed Apr 18 16:55:28 UTC 2018 - Pablo Suárez Hernández 
<psuarezhernan...@suse.com>
+Wed Apr 18 16:55:28 UTC 2018 - psuarezhernan...@suse.com
@@ -138 +191 @@
-Fri Apr 6 16:58:59 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Fri Apr  6 16:58:59 UTC 2018 - mdi...@suse.de
@@ -160 +213 @@
-Thu Apr 5 15:58:22 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Thu Apr  5 15:58:22 UTC 2018 - mdi...@suse.de
@@ -168 +221 @@
-Wed Apr 4 16:32:10 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Wed Apr  4 16:32:10 UTC 2018 - mdi...@suse.de
@@ -179 +232 @@
-Wed Mar 28 12:18:08 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Wed Mar 28 12:18:08 UTC 2018 - mdi...@suse.de
@@ -185 +238 @@
-Wed Mar 28 11:57:30 UTC 2018 - Michael Calmer <m...@suse.de>
+Wed Mar 28 11:57:30 UTC 2018 - m...@suse.de
@@ -209 +262 @@
-Tue Mar 27 16:29:08 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Tue Mar 27 16:29:08 UTC 2018 - mdi...@suse.de
@@ -217 +270 @@
-Fri Mar 23 18:12:09 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Fri Mar 23 18:12:09 UTC 2018 - mdi...@suse.de
@@ -231 +284 @@
-Fri Mar 23 16:19:42 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Fri Mar 23 16:19:42 UTC 2018 - mdi...@suse.de
@@ -244 +297 @@
-Thu Mar 22 14:40:50 UTC 2018 - Pablo Suárez Hernández 
<psuarezhernan...@suse.com>
+Thu Mar 22 14:40:50 UTC 2018 - psuarezhernan...@suse.com
@@ -252 +305 @@
-Thu Mar 22 09:10:33 UTC 2018 - Michael Calmer <m...@suse.de>
+Thu Mar 22 09:10:33 UTC 2018 - m...@suse.de
@@ -267 +320 @@
-Wed Mar 14 09:37:07 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Wed Mar 14 09:37:07 UTC 2018 - mdi...@suse.de
@@ -287 +340 @@
-Tue Mar 13 18:28:03 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Tue Mar 13 18:28:03 UTC 2018 - mdi...@suse.de
@@ -295 +348 @@
-Mon Mar 12 17:47:34 UTC 2018 - Michael Calmer <m...@suse.de>
+Mon Mar 12 17:47:34 UTC 2018 - m...@suse.de
@@ -300 +353 @@
-Sat Mar 10 12:00:17 UTC 2018 - Michael Calmer <m...@suse.de>
+Sat Mar 10 12:00:17 UTC 2018 - m...@suse.de
@@ -314 +367 @@
-Fri Mar 9 15:56:00 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Fri Mar  9 15:56:00 UTC 2018 - mdi...@suse.de
@@ -323 +375,0 @@
-  
@@ -325 +376,0 @@
-  
@@ -327 +377,0 @@
-  
@@ -329 +378,0 @@
-  
@@ -331 +379,0 @@
-  
@@ -333 +380,0 @@
-  
@@ -335 +381,0 @@
-  
@@ -337 +382,0 @@
-  
@@ -339 +383,0 @@
-  
@@ -342 +385,0 @@
-
@@ -344 +387 @@
-Thu Mar 8 11:20:01 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Thu Mar  8 11:20:01 UTC 2018 - mdi...@suse.de
@@ -364 +407 @@
-Fri Mar  2 13:15:46 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Fri Mar  2 13:15:46 UTC 2018 - mdi...@suse.de
@@ -375 +418 @@
-Fri Mar  2 13:15:46 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Fri Mar  2 13:15:46 UTC 2018 - mdi...@suse.de
@@ -383 +426 @@
-Tue Feb 20 10:47:34 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Tue Feb 20 10:47:34 UTC 2018 - mdi...@suse.de
@@ -388 +431 @@
-Tue Feb 13 15:17:11 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Tue Feb 13 15:17:11 UTC 2018 - mdi...@suse.de
@@ -396 +439 @@
-Fri Feb 09 15:39:08 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Fri Feb 09 15:39:08 UTC 2018 - mdi...@suse.de
@@ -428 +471 @@
-Fri Feb 09 15:39:08 UTC 2018 - Jochen Breuer <jbre...@suse.de>
+Fri Feb 09 15:39:08 UTC 2018 - jbre...@suse.de
@@ -438 +481 @@
-Fri Feb 09 15:39:08 UTC 2018 - Jochen Breuer <jbre...@suse.de>
+Fri Feb 09 15:39:08 UTC 2018 - jbre...@suse.de
@@ -445 +488 @@
-Wed Feb 07 13:23:51 UTC 2018 - Mihai Dinca <mdi...@suse.de>
+Wed Feb 07 13:23:51 UTC 2018 - mdi...@suse.de

New:
----
  add-support-for-python-3.7.patch
  change-stringio-import-in-python2-to-import-the-clas.patch
  decode-file-contents-for-python2-bsc-1102013.patch
  fix-for-sorting-of-multi-version-packages-bsc-109717.patch
  fix-for-suse-expanded-support-detection.patch
  fix-mine.get-not-returning-data-workaround-for-48020.patch
  integration-of-msi-authentication-with-azurearm-clou.patch
  only-do-reverse-dns-lookup-on-ips-for-salt-ssh.patch
  prepend-current-directory-when-path-is-just-filename.patch
  use-adler32-algorithm-to-compute-string-checksums.patch
  x509-fixes-111.patch
  x509-fixes-for-remote-signing-106.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ salt.spec ++++++
--- /var/tmp/diff_new_pack.6bpAjw/_old  2018-09-26 14:53:19.811115544 +0200
+++ /var/tmp/diff_new_pack.6bpAjw/_new  2018-09-26 14:53:19.815115539 +0200
@@ -126,6 +126,30 @@
 Patch30:        add-engine-relaying-libvirt-events.patch
 # PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/48781
 Patch31:        avoid-incomprehensive-message-if-crashes.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/48765
+Patch32:        fix-mine.get-not-returning-data-workaround-for-48020.patch
+# PATCH-FIX_OPENSUSE bsc#1097174 and bsc#1097413
+Patch33:        fix-for-sorting-of-multi-version-packages-bsc-109717.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/48863
+Patch34:        decode-file-contents-for-python2-bsc-1102013.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/49052
+Patch35:        add-support-for-python-3.7.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/48771
+Patch36:        only-do-reverse-dns-lookup-on-ips-for-salt-ssh.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/49277
+Patch37:        prepend-current-directory-when-path-is-just-filename.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/49063
+Patch38:        integration-of-msi-authentication-with-azurearm-clou.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/49538
+Patch39:        fix-for-suse-expanded-support-detection.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/49508
+Patch40:        x509-fixes-for-remote-signing-106.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/49555
+Patch41:        change-stringio-import-in-python2-to-import-the-clas.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/48812
+Patch42:        use-adler32-algorithm-to-compute-string-checksums.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/49497
+Patch43:        x509-fixes-111.patch
 
 # BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
@@ -615,6 +639,18 @@
 %patch29 -p1
 %patch30 -p1
 %patch31 -p1
+%patch32 -p1
+%patch33 -p1
+%patch34 -p1
+%patch35 -p1
+%patch36 -p1
+%patch37 -p1
+%patch38 -p1
+%patch39 -p1
+%patch40 -p1
+%patch41 -p1
+%patch42 -p1
+%patch43 -p1
 
 %build
 %if 0%{?build_py2}
@@ -1256,8 +1292,12 @@
 %{_mandir}/man1/salt-call.1.gz
 %{_mandir}/man1/spm.1.gz
 %config(noreplace) %{_sysconfdir}/logrotate.d/salt
+%if 0%{?suse_version} < 1500
+%doc LICENSE AUTHORS README.rst HACKING.rst README.SUSE
+%else
 %license LICENSE
 %doc AUTHORS README.rst HACKING.rst README.SUSE
+%endif
 #
 %dir        %attr(0750, root, salt) %{_sysconfdir}/salt
 %dir        %attr(0750, root, salt) %{_sysconfdir}/salt/pki

++++++ _lastrevision ++++++
--- /var/tmp/diff_new_pack.6bpAjw/_old  2018-09-26 14:53:19.883115434 +0200
+++ /var/tmp/diff_new_pack.6bpAjw/_new  2018-09-26 14:53:19.887115428 +0200
@@ -1 +1 @@
-eb0ca38e07c96eb021ac7490ac1f61a54dc9d904
+ebc77d067d9fa300bdc5bb5dcccaa09e1787f688
\ No newline at end of file

++++++ add-support-for-python-3.7.patch ++++++
++++ 1171 lines (skipped)

++++++ change-stringio-import-in-python2-to-import-the-clas.patch ++++++
>From a0d5af98c8d2a22c5eb56943ff320ca287fa79ea Mon Sep 17 00:00:00 2001
From: Florian Bergmann <bergma...@users.noreply.github.com>
Date: Tue, 11 Sep 2018 14:03:33 +0200
Subject: [PATCH] Change StringIO import in python2 to import the class.
 (#107)

Instead of using StringIO in python3, use the correct BytesIO class instead.
---
 salt/modules/hashutil.py | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/salt/modules/hashutil.py b/salt/modules/hashutil.py
index 721957973d..5123cc7cd7 100644
--- a/salt/modules/hashutil.py
+++ b/salt/modules/hashutil.py
@@ -17,9 +17,10 @@ import salt.utils.hashutils
 import salt.utils.stringutils
 
 if six.PY2:
-    import StringIO
+    from StringIO import StringIO
+    BytesIO = StringIO
 elif six.PY3:
-    from io import StringIO
+    from io import BytesIO, StringIO
 
 
 def digest(instr, checksum='md5'):
@@ -155,13 +156,13 @@ def base64_encodefile(fname):
 
         salt '*' hashutil.base64_encodefile /path/to/binary_file
     '''
-    encoded_f = StringIO.StringIO()
+    encoded_f = BytesIO()
 
     with salt.utils.files.fopen(fname, 'rb') as f:
         base64.encode(f, encoded_f)
 
     encoded_f.seek(0)
-    return encoded_f.read()
+    return salt.utils.stringutils.to_str(encoded_f.read())
 
 
 def base64_decodestring(instr):
@@ -192,7 +193,7 @@ def base64_decodefile(instr, outfile):
 
         salt '*' hashutil.base64_decodefile instr='Z2V0IHNhbHRlZAo=' 
outfile='/path/to/binary_file'
     '''
-    encoded_f = StringIO.StringIO(instr)
+    encoded_f = StringIO(instr)
 
     with salt.utils.files.fopen(outfile, 'wb') as f:
         base64.decode(encoded_f, f)
-- 
2.19.0


++++++ decode-file-contents-for-python2-bsc-1102013.patch ++++++
>From 58913b6801b92bd59374cd53fa48fa74171abb73 Mon Sep 17 00:00:00 2001
From: Abid Mehmood <amehm...@suse.de>
Date: Wed, 1 Aug 2018 17:19:11 +0200
Subject: [PATCH] Decode file contents for python2(bsc#1102013)

---
 salt/states/file.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/salt/states/file.py b/salt/states/file.py
index e1d247ae4f..db82098a33 100644
--- a/salt/states/file.py
+++ b/salt/states/file.py
@@ -1105,8 +1105,7 @@ def _get_template_texts(source_list=None,
             tmplines = None
             with salt.utils.files.fopen(rndrd_templ_fn, 'rb') as fp_:
                 tmplines = fp_.read()
-                if six.PY3:
-                    tmplines = tmplines.decode(__salt_system_encoding__)
+                tmplines = tmplines.decode(__salt_system_encoding__)
                 tmplines = tmplines.splitlines(True)
             if not tmplines:
                 msg = 'Failed to read rendered template file {0} ({1})'
-- 
2.17.1


++++++ fix-for-sorting-of-multi-version-packages-bsc-109717.patch ++++++
>From f0f63dc8dd5979b51db71cf759d4350da1078383 Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbre...@suse.de>
Date: Wed, 13 Jun 2018 17:51:13 +0200
Subject: [PATCH] Fix for sorting of multi-version packages (bsc#1097174
 and bsc#1097413)

---
 salt/modules/rpm.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py
index 3683234f59..8e71992f81 100644
--- a/salt/modules/rpm.py
+++ b/salt/modules/rpm.py
@@ -9,6 +9,7 @@ import logging
 import os
 import re
 import datetime
+from distutils.version import LooseVersion
 
 # Import Salt libs
 import salt.utils.decorators.path
@@ -609,7 +610,7 @@ def info(*packages, **kwargs):
     # pick only latest versions
     # (in case multiple packages installed, e.g. kernel)
     ret = dict()
-    for pkg_data in reversed(sorted(_ret, key=lambda x: x['edition'])):
+    for pkg_data in reversed(sorted(_ret, key=lambda x: 
LooseVersion(x['edition']))):
         pkg_name = pkg_data.pop('name')
         # Filter out GPG public keys packages
         if pkg_name.startswith('gpg-pubkey'):
-- 
2.17.1


++++++ fix-for-suse-expanded-support-detection.patch ++++++
>From 1c9cba3a397d53e399b82320507fb5141234c67f Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbre...@suse.de>
Date: Thu, 6 Sep 2018 17:15:18 +0200
Subject: [PATCH] Fix for SUSE Expanded Support detection

A SUSE ES installation has both, the centos-release and redhat-release
file. Since os_data only used the centos-release file to detect a
CentOS installation, this lead to SUSE ES being detected as CentOS.

This change also adds a check for redhat-release and then marks the
'lsb_distrib_id' as RedHat.
---
 salt/grains/core.py | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/salt/grains/core.py b/salt/grains/core.py
index dc472a6c0a..a5c3a6a8cf 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1593,8 +1593,17 @@ def os_data():
                                 grains['lsb_distrib_codename'] = \
                                     comps[3].replace('(', '').replace(')', '')
                 elif os.path.isfile('/etc/centos-release'):
-                    # CentOS Linux
-                    grains['lsb_distrib_id'] = 'CentOS'
+                    log.trace('Parsing distrib info from /etc/centos-release')
+                    # Maybe CentOS Linux; could also be SUSE Expanded Support.
+                    # SUSE ES has both, centos-release and redhat-release.
+                    if os.path.isfile('/etc/redhat-release'):
+                        with salt.utils.files.fopen('/etc/redhat-release') as 
ifile:
+                            for line in ifile:
+                                if "red hat enterprise linux server" in 
line.lower():
+                                    # This is a SUSE Expanded Support Rhel 
installation
+                                    grains['lsb_distrib_id'] = 'RedHat'
+                                    break
+                    grains.setdefault('lsb_distrib_id', 'CentOS')
                     with salt.utils.files.fopen('/etc/centos-release') as 
ifile:
                         for line in ifile:
                             # Need to pull out the version and codename
-- 
2.19.0


++++++ fix-mine.get-not-returning-data-workaround-for-48020.patch ++++++
>From f8c0811c3a05ef334eef1943a906fe01b13c1afc Mon Sep 17 00:00:00 2001
From: Federico Ceratto <federico.cera...@suse.com>
Date: Wed, 25 Jul 2018 10:33:09 +0000
Subject: [PATCH] Fix mine.get not returning data (Workaround for #48020)

---
 salt/utils/minions.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/salt/utils/minions.py b/salt/utils/minions.py
index c3acc6ba90..bb0cbaa589 100644
--- a/salt/utils/minions.py
+++ b/salt/utils/minions.py
@@ -239,12 +239,12 @@ class CkMinions(object):
         Retreive complete minion list from PKI dir.
         Respects cache if configured
         '''
-        if self.opts.get('__role') == 'master' and self.opts.get('__cli') == 
'salt-run':
-            # Compiling pillar directly on the master, just return the master's
-            # ID as that is the only one that is available.
-            return [self.opts['id']]
         minions = []
         pki_cache_fn = os.path.join(self.opts['pki_dir'], self.acc, 
'.key_cache')
+        try:
+            os.makedirs(os.path.dirname(pki_cache_fn))
+        except OSError:
+            pass
         try:
             if self.opts['key_cache'] and os.path.exists(pki_cache_fn):
                 log.debug('Returning cached minion list')
-- 
2.17.1


++++++ integration-of-msi-authentication-with-azurearm-clou.patch ++++++
>From 06aff97c83342cf9635fa750222f774ab1664a0d Mon Sep 17 00:00:00 2001
From: ed lane <ed.lan...@gmail.com>
Date: Thu, 30 Aug 2018 06:07:08 -0600
Subject: [PATCH] Integration of MSI authentication with azurearm cloud
 driver (#105)

---
 salt/cloud/clouds/azurearm.py | 47 +++++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py
index bd9a25a7e2..8b9a9e8903 100644
--- a/salt/cloud/clouds/azurearm.py
+++ b/salt/cloud/clouds/azurearm.py
@@ -25,6 +25,9 @@ The Azure cloud module is used to control access to Microsoft 
Azure
     * ``client_id``
     * ``secret``
 
+    if using MSI-style authentication:
+    * ``subscription_id``
+
 Example ``/etc/salt/cloud.providers`` or
 ``/etc/salt/cloud.providers.d/azure.conf`` configuration:
 
@@ -48,6 +51,10 @@ Example ``/etc/salt/cloud.providers`` or
       For example, this creates a service principal with 'owner' role for the 
whole subscription:
       az ad sp create-for-rbac -n "http://mysaltapp"; --role owner --scopes 
/subscriptions/3287abc8-f98a-c678-3bde-326766fd3617
       *Note: review the details of Service Principals. Owner role is more than 
you normally need, and you can restrict scope to a resource group or individual 
resources.
+
+    Or my-azure-config with MSI-style authentication:
+      driver: azure
+      subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617
 '''
 # pylint: disable=E0102
 
@@ -86,6 +93,7 @@ try:
         UserPassCredentials,
         ServicePrincipalCredentials,
     )
+    from msrestazure.azure_active_directory import MSIAuthentication
     from azure.mgmt.compute import ComputeManagementClient
     from azure.mgmt.compute.models import (
         CachingTypes,
@@ -166,19 +174,30 @@ def get_configured_provider():
     '''
     Return the first configured instance.
     '''
+    # check if using Service Principle style authentication...
     provider = config.is_provider_configured(
         __opts__,
         __active_provider_name__ or __virtualname__,
-        ('subscription_id', 'tenant', 'client_id', 'secret')
+        required_keys=('subscription_id', 'tenant', 'client_id', 'secret'),
+        log_message=False  #... allowed to fail so no need to log warnings
         )
     if provider is False:
-        return config.is_provider_configured(
+        # check if using username/password style authentication...
+        provider = config.is_provider_configured(
             __opts__,
             __active_provider_name__ or __virtualname__,
-            ('subscription_id', 'username', 'password')
+            required_keys=('subscription_id', 'username', 'password'),
+            log_message=False
         )
-    else:
-        return provider
+    if provider is False:
+        # check if using MSI style credentials...
+        provider = config.is_provider_configured(
+            __opts__,
+            __active_provider_name__ or __virtualname__,
+            required_keys=('subscription_id',),
+            log_message=False
+        )
+    return provider
 
 
 def get_dependencies():
@@ -210,6 +229,7 @@ def get_conn(Client=None):
         get_configured_provider(), __opts__, search_global=False
     )
     if tenant is not None:
+        # using Service Principle style authentication...
         client_id = config.get_cloud_config_value(
             'client_id',
             get_configured_provider(), __opts__, search_global=False
@@ -224,15 +244,20 @@ def get_conn(Client=None):
             'username',
             get_configured_provider(), __opts__, search_global=False
         )
-        password = config.get_cloud_config_value(
-            'password',
-            get_configured_provider(), __opts__, search_global=False
-        )
-        credentials = UserPassCredentials(username, password)
+        if username is not None:
+            # using username/password style authentication...
+            password = config.get_cloud_config_value(
+                'password',
+                get_configured_provider(), __opts__, search_global=False
+            )
+            credentials = UserPassCredentials(username, password)
+        else:
+            # using MSI style authentication ...
+            credentials = MSIAuthentication()
 
     client = Client(
         credentials=credentials,
-        subscription_id=subscription_id,
+        subscription_id=str(subscription_id),
     )
     
client.config.add_user_agent('SaltCloud/{0}'.format(salt.version.__version__))
     return client
-- 
2.19.0


++++++ only-do-reverse-dns-lookup-on-ips-for-salt-ssh.patch ++++++
>From f346e83f6d4651a1cdcaad8c995642b55f66ddbc Mon Sep 17 00:00:00 2001
From: Daniel Wallace <danielwall...@gtmanfred.com>
Date: Wed, 25 Jul 2018 09:48:29 -0500
Subject: [PATCH] only do reverse dns lookup on ips for salt-ssh

Fixes #48676
---
 salt/client/ssh/__init__.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index 8a85cc2480..d6ff0c3479 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -349,7 +349,9 @@ class SSH(object):
             return
 
         hostname = self.opts['tgt'].split('@')[-1]
-        needs_expansion = '*' not in hostname and 
salt.utils.network.is_reachable_host(hostname)
+        needs_expansion = '*' not in hostname and \
+                          salt.utils.network.is_reachable_host(hostname) and \
+                          salt.utils.network.is_ip(hostname)
         if needs_expansion:
             hostname = salt.utils.network.ip_to_host(hostname)
             if hostname is None:
-- 
2.17.1


++++++ prepend-current-directory-when-path-is-just-filename.patch ++++++
>From 341ee0c44cabf2f34bdd2f4b54e4b83053a3133e Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdi...@suse.de>
Date: Thu, 23 Aug 2018 16:14:36 +0200
Subject: [PATCH] Prepend current directory when path is just filename
 (bsc#1095942)

---
 salt/utils/parsers.py | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py
index 5a415ab576..9a7f27ac11 100644
--- a/salt/utils/parsers.py
+++ b/salt/utils/parsers.py
@@ -591,10 +591,19 @@ class LogLevelMixIn(six.with_metaclass(MixInMeta, 
object)):
                 )
             )
 
+        def _logfile_callback(option, opt, value, parser, *args, **kwargs):
+            if not os.path.dirname(value):
+                # if the path is only a file name (no parent directory), 
assume current directory
+                value = os.path.join(os.path.curdir, value)
+            setattr(parser.values, self._logfile_config_setting_name_, value)
+
         group.add_option(
             '--log-file',
             dest=self._logfile_config_setting_name_,
             default=None,
+            action='callback',
+            type='string',
+            callback=_logfile_callback,
             help='Log file path. Default: \'{0}\'.'.format(
                 self._default_logging_logfile_
             )
-- 
2.19.0


++++++ use-adler32-algorithm-to-compute-string-checksums.patch ++++++
>From 1cb2d2bc6c1cf1a39e735120c184d6ade9e64c34 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <b...@suse.de>
Date: Sat, 28 Jul 2018 22:59:04 +0200
Subject: [PATCH] Use Adler32 algorithm to compute string checksums

Generate the same numeric value across all Python versions and platforms

Re-add getting hash by Python shell-out method

Add an option to choose between default hashing, Adler32 or CRC32 algorithms

Set default config option  for server_id hashing to False on minion

Choose CRC method, default to faster but less reliable "adler32", if crc is in 
use

Add warning for Sodium.
---
 salt/config/__init__.py | 13 +++++++++-
 salt/grains/core.py     | 54 +++++++++++++++++++++++++++--------------
 2 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/salt/config/__init__.py b/salt/config/__init__.py
index feda0abac1..59df7e1cba 100644
--- a/salt/config/__init__.py
+++ b/salt/config/__init__.py
@@ -1186,6 +1186,16 @@ VALID_OPTS = {
 
     # Enable calling ssh minions from the salt master
     'enable_ssh_minions': bool,
+
+    # Thorium saltenv
+    'thoriumenv': (type(None), six.string_types),
+
+    # Thorium top file location
+    'thorium_top': six.string_types,
+
+    # Use Adler32 hashing algorithm for server_id (default False until Sodium, 
"adler32" after)
+    # Possible values are: False, adler32, crc32
+    'server_id_use_crc': (bool, six.string_types),
 }
 
 # default configurations
@@ -1486,7 +1496,8 @@ DEFAULT_MINION_OPTS = {
     },
     'discovery': False,
     'schedule': {},
-    'ssh_merge_pillar': True
+    'ssh_merge_pillar': True,
+    'server_id_use_crc': False,
 }
 
 DEFAULT_MASTER_OPTS = {
diff --git a/salt/grains/core.py b/salt/grains/core.py
index a5c3a6a8cf..6aaf38096d 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -20,6 +20,7 @@ import platform
 import logging
 import locale
 import uuid
+import zlib
 from errno import EACCES, EPERM
 import datetime
 
@@ -46,6 +47,8 @@ import salt.utils.files
 import salt.utils.network
 import salt.utils.path
 import salt.utils.platform
+import salt.utils.stringutils
+import salt.utils.versions
 from salt.ext import six
 from salt.ext.six.moves import range
 
@@ -2420,40 +2423,55 @@ def _hw_data(osdata):
     return grains
 
 
-def get_server_id():
+def _get_hash_by_shell():
     '''
-    Provides an integer based on the FQDN of a machine.
-    Useful as server-id in MySQL replication or anywhere else you'll need an ID
-    like this.
+    Shell-out Python 3 for compute reliable hash
+    :return:
     '''
-    # Provides:
-    #   server_id
-
-    if salt.utils.platform.is_proxy():
-        return {}
     id_ = __opts__.get('id', '')
     id_hash = None
     py_ver = sys.version_info[:2]
     if py_ver >= (3, 3):
         # Python 3.3 enabled hash randomization, so we need to shell out to get
         # a reliable hash.
-        id_hash = __salt__['cmd.run'](
-            [sys.executable, '-c', 'print(hash("{0}"))'.format(id_)],
-            env={'PYTHONHASHSEED': '0'}
-        )
+        id_hash = __salt__['cmd.run']([sys.executable, '-c', 
'print(hash("{0}"))'.format(id_)],
+                                      env={'PYTHONHASHSEED': '0'})
         try:
             id_hash = int(id_hash)
         except (TypeError, ValueError):
-            log.debug(
-                'Failed to hash the ID to get the server_id grain. Result of '
-                'hash command: %s', id_hash
-            )
+            log.debug('Failed to hash the ID to get the server_id grain. 
Result of hash command: %s', id_hash)
             id_hash = None
     if id_hash is None:
         # Python < 3.3 or error encountered above
         id_hash = hash(id_)
 
-    return {'server_id': abs(id_hash % (2 ** 31))}
+    return abs(id_hash % (2 ** 31))
+
+
+def get_server_id():
+    '''
+    Provides an integer based on the FQDN of a machine.
+    Useful as server-id in MySQL replication or anywhere else you'll need an ID
+    like this.
+    '''
+    # Provides:
+    #   server_id
+
+    if salt.utils.platform.is_proxy():
+        server_id = {}
+    else:
+        use_crc = __opts__.get('server_id_use_crc')
+        if bool(use_crc):
+            id_hash = getattr(zlib, use_crc, zlib.adler32)(__opts__.get('id', 
'').encode()) & 0xffffffff
+        else:
+            salt.utils.versions.warn_until('Sodium', 'This server_id is 
computed nor by Adler32 neither by CRC32. '
+                                                     'Please use 
"server_id_use_crc" option and define algorithm you'
+                                                     'prefer (default 
"Adler32"). The server_id will be computed with'
+                                                     'Adler32 by default.')
+            id_hash = _get_hash_by_shell()
+        server_id = {'server_id': id_hash}
+
+    return server_id
 
 
 def get_master():
-- 
2.19.0


++++++ x509-fixes-111.patch ++++++
>From 053d97afcc7486f7300e339bc56cb3c850cc523b Mon Sep 17 00:00:00 2001
From: Florian Bergmann <bergma...@users.noreply.github.com>
Date: Fri, 14 Sep 2018 10:30:39 +0200
Subject: [PATCH] X509 fixes (#111)

* Return proper content type for the x509 certificate

* Remove parenthesis

* Remove extra-variables during the import

* Comment fix

* Remove double returns

* Change log level from trace to debug

* Remove 'pass' and add logging instead

* Remove unnecessary wrapping

Remove wrapping

* PEP 8: line too long

PEP8: line too long

* PEP8: Redefine RSAError variable in except clause

* Do not return None if name was not found

* Do not return None if no matched minions found

* Fix unit tests
---
 salt/modules/publish.py         |   8 +-
 salt/modules/x509.py            | 132 ++++++++++++--------------------
 salt/states/x509.py             |  22 ++++--
 tests/unit/modules/test_x509.py |   9 ++-
 4 files changed, 74 insertions(+), 97 deletions(-)

diff --git a/salt/modules/publish.py b/salt/modules/publish.py
index 2de99583f4..ac31b4b65f 100644
--- a/salt/modules/publish.py
+++ b/salt/modules/publish.py
@@ -83,10 +83,8 @@ def _publish(
                     in minion configuration but `via_master` was specified.')
         else:
             # Find the master in the list of master_uris generated by the 
minion base class
-            matching_master_uris = [master for master
-                    in __opts__['master_uri_list']
-                    if '//{0}:'.format(via_master)
-                    in master]
+            matching_master_uris = [master for master in 
__opts__['master_uri_list']
+                                    if '//{0}:'.format(via_master) in master]
 
             if not matching_master_uris:
                 raise SaltInvocationError('Could not find match for {0} in \
@@ -176,6 +174,8 @@ def _publish(
         else:
             return ret
 
+    return {}
+
 
 def publish(tgt,
             fun,
diff --git a/salt/modules/x509.py b/salt/modules/x509.py
index 9901bc5bd9..45afcccd99 100644
--- a/salt/modules/x509.py
+++ b/salt/modules/x509.py
@@ -36,14 +36,13 @@ from salt.state import STATE_INTERNAL_KEYWORDS as 
_STATE_INTERNAL_KEYWORDS
 # Import 3rd Party Libs
 try:
     import M2Crypto
-    HAS_M2 = True
 except ImportError:
-    HAS_M2 = False
+    M2Crypto = None
+
 try:
     import OpenSSL
-    HAS_OPENSSL = True
 except ImportError:
-    HAS_OPENSSL = False
+    OpenSSL = None
 
 __virtualname__ = 'x509'
 
@@ -81,10 +80,7 @@ def __virtual__():
     '''
     only load this module if m2crypto is available
     '''
-    if HAS_M2:
-        return __virtualname__
-    else:
-        return (False, 'Could not load x509 module, m2crypto unavailable')
+    return __virtualname__ if M2Crypto is not None else False, 'Could not load 
x509 module, m2crypto unavailable'
 
 
 class _Ctx(ctypes.Structure):
@@ -127,10 +123,8 @@ def _new_extension(name, value, critical=0, issuer=None, 
_pyfree=1):
     doesn't support getting the publickeyidentifier from the issuer
     to create the authoritykeyidentifier extension.
     '''
-    if name == 'subjectKeyIdentifier' and \
-            value.strip('0123456789abcdefABCDEF:') is not '':
-        raise salt.exceptions.SaltInvocationError(
-            'value must be precomputed hash')
+    if name == 'subjectKeyIdentifier' and 
value.strip('0123456789abcdefABCDEF:') is not '':
+        raise salt.exceptions.SaltInvocationError('value must be precomputed 
hash')
 
     # ensure name and value are bytes
     name = salt.utils.stringutils.to_str(name)
@@ -145,7 +139,7 @@ def _new_extension(name, value, critical=0, issuer=None, 
_pyfree=1):
         x509_ext_ptr = M2Crypto.m2.x509v3_ext_conf(None, ctx, name, value)
         lhash = None
     except AttributeError:
-        lhash = M2Crypto.m2.x509v3_lhash()                      # pylint: 
disable=no-member
+        lhash = M2Crypto.m2.x509v3_lhash()  # pylint: disable=no-member
         ctx = M2Crypto.m2.x509v3_set_conf_lhash(
             lhash)          # pylint: disable=no-member
         # ctx not zeroed
@@ -196,10 +190,8 @@ def _get_csr_extensions(csr):
     csrtempfile.flush()
     csryaml = _parse_openssl_req(csrtempfile.name)
     csrtempfile.close()
-    if csryaml and 'Requested Extensions' in \
-            csryaml['Certificate Request']['Data']:
-        csrexts = \
-            csryaml['Certificate Request']['Data']['Requested Extensions']
+    if csryaml and 'Requested Extensions' in csryaml['Certificate 
Request']['Data']:
+        csrexts = csryaml['Certificate Request']['Data']['Requested 
Extensions']
 
         if not csrexts:
             return ret
@@ -294,7 +286,7 @@ def _get_signing_policy(name):
         signing_policy = policies.get(name)
         if signing_policy:
             return signing_policy
-    return __salt__['config.get']('x509_signing_policies', {}).get(name)
+    return __salt__['config.get']('x509_signing_policies', {}).get(name) or {}
 
 
 def _pretty_hex(hex_str):
@@ -321,9 +313,11 @@ def _text_or_file(input_):
     '''
     if os.path.isfile(input_):
         with salt.utils.files.fopen(input_) as fp_:
-            return salt.utils.stringutils.to_str(fp_.read())
+            out = salt.utils.stringutils.to_str(fp_.read())
     else:
-        return salt.utils.stringutils.to_str(input_)
+        out = salt.utils.stringutils.to_str(input_)
+
+    return out
 
 
 def _parse_subject(subject):
@@ -341,7 +335,7 @@ def _parse_subject(subject):
                 ret[nid_name] = val
                 nids.append(nid_num)
         except TypeError as err:
-            log.trace("Missing attribute '%s'. Error: %s", nid_name, err)
+            log.debug("Missing attribute '%s'. Error: %s", nid_name, err)
 
     return ret
 
@@ -520,8 +514,8 @@ def get_pem_entries(glob_path):
         if os.path.isfile(path):
             try:
                 ret[path] = get_pem_entry(text=path)
-            except ValueError:
-                pass
+            except ValueError as err:
+                log.debug('Unable to get PEM entries from %s: %s', path, err)
 
     return ret
 
@@ -599,8 +593,8 @@ def read_certificates(glob_path):
         if os.path.isfile(path):
             try:
                 ret[path] = read_certificate(certificate=path)
-            except ValueError:
-                pass
+            except ValueError as err:
+                log.debug('Unable to read certificate %s: %s', path, err)
 
     return ret
 
@@ -629,12 +623,10 @@ def read_csr(csr):
         # Get size returns in bytes. The world thinks of key sizes in bits.
         'Subject': _parse_subject(csr.get_subject()),
         'Subject Hash': _dec2hex(csr.get_subject().as_hash()),
-        'Public Key Hash': hashlib.sha1(csr.get_pubkey().get_modulus())\
-        .hexdigest()
+        'Public Key Hash': 
hashlib.sha1(csr.get_pubkey().get_modulus()).hexdigest(),
+        'X509v3 Extensions': _get_csr_extensions(csr),
     }
 
-    ret['X509v3 Extensions'] = _get_csr_extensions(csr)
-
     return ret
 
 
@@ -937,7 +929,7 @@ def create_crl(  # pylint: 
disable=too-many-arguments,too-many-locals
     # pyOpenSSL Note due to current limitations in pyOpenSSL it is impossible
     # to specify a digest For signing the CRL. This will hopefully be fixed
     # soon: https://github.com/pyca/pyopenssl/pull/161
-    if not HAS_OPENSSL:
+    if OpenSSL is None:
         raise salt.exceptions.SaltInvocationError(
             'Could not load OpenSSL module, OpenSSL unavailable'
         )
@@ -962,8 +954,7 @@ def create_crl(  # pylint: 
disable=too-many-arguments,too-many-locals
                 continue
 
         if 'revocation_date' not in rev_item:
-            rev_item['revocation_date'] = datetime.datetime\
-                .now().strftime('%Y-%m-%d %H:%M:%S')
+            rev_item['revocation_date'] = 
datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
 
         rev_date = datetime.datetime.strptime(
             rev_item['revocation_date'], '%Y-%m-%d %H:%M:%S')
@@ -1002,8 +993,9 @@ def create_crl(  # pylint: 
disable=too-many-arguments,too-many-locals
     try:
         crltext = crl.export(**export_kwargs)
     except (TypeError, ValueError):
-        log.warning(
-            'Error signing crl with specified digest. Are you using pyopenssl 
0.15 or newer? The default md5 digest will be used.')
+        log.warning('Error signing crl with specified digest. '
+                    'Are you using pyopenssl 0.15 or newer? '
+                    'The default md5 digest will be used.')
         export_kwargs.pop('digest', None)
         crltext = crl.export(**export_kwargs)
 
@@ -1042,8 +1034,7 @@ def sign_remote_certificate(argdic, **kwargs):
     if 'signing_policy' in argdic:
         signing_policy = _get_signing_policy(argdic['signing_policy'])
         if not signing_policy:
-            return 'Signing policy {0} does not exist.'.format(
-                argdic['signing_policy'])
+            return 'Signing policy {0} does not 
exist.'.format(argdic['signing_policy'])
 
         if isinstance(signing_policy, list):
             dict_ = {}
@@ -1080,6 +1071,7 @@ def get_signing_policy(signing_policy_name):
     signing_policy = _get_signing_policy(signing_policy_name)
     if not signing_policy:
         return 'Signing policy {0} does not exist.'.format(signing_policy_name)
+
     if isinstance(signing_policy, list):
         dict_ = {}
         for item in signing_policy:
@@ -1092,10 +1084,9 @@ def get_signing_policy(signing_policy_name):
         pass
 
     try:
-        signing_policy['signing_cert'] = get_pem_entry(
-            signing_policy['signing_cert'], 'CERTIFICATE')
+        signing_policy['signing_cert'] = 
get_pem_entry(signing_policy['signing_cert'], 'CERTIFICATE')
     except KeyError:
-        pass
+        log.debug('Unable to get "certificate" PEM entry')
 
     return signing_policy
 
@@ -1346,8 +1337,7 @@ def create_certificate(
         signing_private_key='/etc/pki/myca.key' csr='/etc/pki/myca.csr'}
     '''
 
-    if not path and not text and \
-            ('testrun' not in kwargs or kwargs['testrun'] is False):
+    if not path and not text and ('testrun' not in kwargs or kwargs['testrun'] 
is False):
         raise salt.exceptions.SaltInvocationError(
             'Either path or text must be specified.')
     if path and text:
@@ -1376,8 +1366,7 @@ def create_certificate(
         # Including listen_in and preqreuired because they are not included
         # in STATE_INTERNAL_KEYWORDS
         # for salt 2014.7.2
-        for ignore in list(_STATE_INTERNAL_KEYWORDS) + \
-                ['listen_in', 'preqrequired', '__prerequired__']:
+        for ignore in list(_STATE_INTERNAL_KEYWORDS) + ['listen_in', 
'preqrequired', '__prerequired__']:
             kwargs.pop(ignore, None)
 
         certs = __salt__['publish.publish'](
@@ -1484,8 +1473,7 @@ def create_certificate(
             continue
 
         # Use explicitly set values first, fall back to CSR values.
-        extval = kwargs.get(extname) or kwargs.get(extlongname) or \
-            csrexts.get(extname) or csrexts.get(extlongname)
+        extval = kwargs.get(extname) or kwargs.get(extlongname) or 
csrexts.get(extname) or csrexts.get(extlongname)
 
         critical = False
         if extval.startswith('critical '):
@@ -1608,8 +1596,8 @@ def create_csr(path=None, text=False, **kwargs):
 
     if 'private_key' not in kwargs and 'public_key' in kwargs:
         kwargs['private_key'] = kwargs['public_key']
-        log.warning(
-            "OpenSSL no longer allows working with non-signed CSRs. A 
private_key must be specified. Attempting to use public_key as private_key")
+        log.warning("OpenSSL no longer allows working with non-signed CSRs. "
+                    "A private_key must be specified. Attempting to use 
public_key as private_key")
 
     if 'private_key' not in kwargs:
         raise salt.exceptions.SaltInvocationError('private_key is required')
@@ -1621,11 +1609,9 @@ def create_csr(path=None, text=False, **kwargs):
         kwargs['private_key_passphrase'] = None
     if 'public_key_passphrase' not in kwargs:
         kwargs['public_key_passphrase'] = None
-    if kwargs['public_key_passphrase'] and not kwargs[
-            'private_key_passphrase']:
+    if kwargs['public_key_passphrase'] and not 
kwargs['private_key_passphrase']:
         kwargs['private_key_passphrase'] = kwargs['public_key_passphrase']
-    if kwargs['private_key_passphrase'] and not kwargs[
-            'public_key_passphrase']:
+    if kwargs['private_key_passphrase'] and not 
kwargs['public_key_passphrase']:
         kwargs['public_key_passphrase'] = kwargs['private_key_passphrase']
 
     csr.set_pubkey(get_public_key(kwargs['public_key'],
@@ -1669,18 +1655,10 @@ def create_csr(path=None, text=False, **kwargs):
         extstack.push(ext)
 
     csr.add_extensions(extstack)
-
     csr.sign(_get_private_key_obj(kwargs['private_key'],
                                   
passphrase=kwargs['private_key_passphrase']), kwargs['algorithm'])
 
-    if path:
-        return write_pem(
-            text=csr.as_pem(),
-            path=path,
-            pem_type='CERTIFICATE REQUEST'
-        )
-    else:
-        return csr.as_pem()
+    return write_pem(text=csr.as_pem(), path=path, pem_type='CERTIFICATE 
REQUEST') if path else csr.as_pem()
 
 
 def verify_private_key(private_key, public_key, passphrase=None):
@@ -1705,8 +1683,7 @@ def verify_private_key(private_key, public_key, 
passphrase=None):
         salt '*' x509.verify_private_key private_key=/etc/pki/myca.key \\
                 public_key=/etc/pki/myca.crt
     '''
-    return bool(get_public_key(private_key, passphrase)
-                == get_public_key(public_key))
+    return get_public_key(private_key, passphrase) == 
get_public_key(public_key)
 
 
 def verify_signature(certificate, signing_pub_key=None,
@@ -1760,9 +1737,8 @@ def verify_crl(crl, cert):
         salt '*' x509.verify_crl crl=/etc/pki/myca.crl cert=/etc/pki/myca.crt
     '''
     if not salt.utils.path.which('openssl'):
-        raise salt.exceptions.SaltInvocationError(
-            'openssl binary not found in path'
-        )
+        raise salt.exceptions.SaltInvocationError('External command "openssl" 
not found')
+
     crltext = _text_or_file(crl)
     crltext = get_pem_entry(crltext, pem_type='X509 CRL')
     crltempfile = tempfile.NamedTemporaryFile()
@@ -1783,10 +1759,7 @@ def verify_crl(crl, cert):
     crltempfile.close()
     certtempfile.close()
 
-    if 'verify OK' in output:
-        return True
-    else:
-        return False
+    return 'verify OK' in output
 
 
 def expired(certificate):
@@ -1823,8 +1796,9 @@ def expired(certificate):
                 ret['expired'] = True
             else:
                 ret['expired'] = False
-        except ValueError:
-            pass
+        except ValueError as err:
+            log.debug('Failed to get data of expired certificate: %s', err)
+            log.trace(err, exc_info=True)
 
     return ret
 
@@ -1847,6 +1821,7 @@ def will_expire(certificate, days):
 
         salt '*' x509.will_expire "/etc/pki/mycert.crt" days=30
     '''
+    ts_pt = "%Y-%m-%d %H:%M:%S"
     ret = {}
 
     if os.path.isfile(certificate):
@@ -1856,18 +1831,13 @@ def will_expire(certificate, days):
 
             cert = _get_certificate_obj(certificate)
 
-            _check_time = datetime.datetime.utcnow() + \
-                datetime.timedelta(days=days)
+            _check_time = datetime.datetime.utcnow() + 
datetime.timedelta(days=days)
             _expiration_date = cert.get_not_after().get_datetime()
 
             ret['cn'] = _parse_subject(cert.get_subject())['CN']
-
-            if _expiration_date.strftime("%Y-%m-%d %H:%M:%S") <= \
-                    _check_time.strftime("%Y-%m-%d %H:%M:%S"):
-                ret['will_expire'] = True
-            else:
-                ret['will_expire'] = False
-        except ValueError:
-            pass
+            ret['will_expire'] = _expiration_date.strftime(ts_pt) <= 
_check_time.strftime(ts_pt)
+        except ValueError as err:
+            log.debug('Unable to return details of a sertificate expiration: 
%s', err)
+            log.trace(err, exc_info=True)
 
     return ret
diff --git a/salt/states/x509.py b/salt/states/x509.py
index 7bb941f393..3ba4f79c79 100644
--- a/salt/states/x509.py
+++ b/salt/states/x509.py
@@ -163,6 +163,7 @@ import copy
 
 # Import Salt Libs
 import salt.exceptions
+import salt.utils.stringutils
 
 # Import 3rd-party libs
 from salt.ext import six
@@ -170,7 +171,7 @@ from salt.ext import six
 try:
     from M2Crypto.RSA import RSAError
 except ImportError:
-    pass
+    RSAError = Exception('RSA Error')
 
 
 def __virtual__():
@@ -180,7 +181,7 @@ def __virtual__():
     if 'x509.get_pem_entry' in __salt__:
         return 'x509'
     else:
-        return (False, 'Could not load x509 state: m2crypto unavailable')
+        return False, 'Could not load x509 state: the x509 is not available'
 
 
 def _revoked_to_list(revs):
@@ -267,7 +268,8 @@ def private_key_managed(name,
 
     new:
         Always create a new key. Defaults to False.
-        Combining new with :mod:`prereq <salt.states.requsities.preqreq>`, or 
when used as part of a `managed_private_key` can allow key rotation whenever a 
new certificiate is generated.
+        Combining new with :mod:`prereq <salt.states.requsities.preqreq>`, or 
when used as part of a
+        `managed_private_key` can allow key rotation whenever a new 
certificiate is generated.
 
     overwrite:
         Overwrite an existing private key if the provided passphrase cannot 
decrypt it.
@@ -453,8 +455,10 @@ def certificate_managed(name,
                 private_key_args['name'], pem_type='RSA PRIVATE KEY')
         else:
             new_private_key = True
-            private_key = __salt__['x509.create_private_key'](text=True, 
bits=private_key_args['bits'], passphrase=private_key_args[
-                                                              'passphrase'], 
cipher=private_key_args['cipher'], verbose=private_key_args['verbose'])
+            private_key = __salt__['x509.create_private_key'](text=True, 
bits=private_key_args['bits'],
+                                                              
passphrase=private_key_args['passphrase'],
+                                                              
cipher=private_key_args['cipher'],
+                                                              
verbose=private_key_args['verbose'])
 
         kwargs['public_key'] = private_key
 
@@ -664,8 +668,10 @@ def crl_managed(name,
     else:
         current = '{0} does not exist.'.format(name)
 
-    new_crl = __salt__['x509.create_crl'](text=True, 
signing_private_key=signing_private_key, 
signing_private_key_passphrase=signing_private_key_passphrase,
-                                          signing_cert=signing_cert, 
revoked=revoked, days_valid=days_valid, digest=digest, 
include_expired=include_expired)
+    new_crl = __salt__['x509.create_crl'](text=True, 
signing_private_key=signing_private_key,
+                                          
signing_private_key_passphrase=signing_private_key_passphrase,
+                                          signing_cert=signing_cert, 
revoked=revoked, days_valid=days_valid,
+                                          digest=digest, 
include_expired=include_expired)
 
     new = __salt__['x509.read_crl'](crl=new_crl)
     new_comp = new.copy()
@@ -707,6 +713,6 @@ def pem_managed(name,
         Any arguments supported by :state:`file.managed 
<salt.states.file.managed>` are supported.
     '''
     file_args, kwargs = _get_file_args(name, **kwargs)
-    file_args['contents'] = __salt__['x509.get_pem_entry'](text=text)
+    file_args['contents'] = 
salt.utils.stringutils.to_str(__salt__['x509.get_pem_entry'](text=text))
 
     return __states__['file.managed'](**file_args)
diff --git a/tests/unit/modules/test_x509.py b/tests/unit/modules/test_x509.py
index c300a56d64..7e00c97140 100644
--- a/tests/unit/modules/test_x509.py
+++ b/tests/unit/modules/test_x509.py
@@ -67,10 +67,11 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
 
         subj = FakeSubject()
         x509._parse_subject(subj)
-        x509.log.trace.assert_called_once()
-        assert x509.log.trace.call_args[0][0] == "Missing attribute '%s'. 
Error: %s"
-        assert x509.log.trace.call_args[0][1] == list(subj.nid.keys())[0]
-        assert isinstance(x509.log.trace.call_args[0][2], TypeError)
+        x509.log.debug.assert_called_once()
+        
+        assert x509.log.debug.call_args[0][0] == "Missing attribute '%s'. 
Error: %s"
+        assert x509.log.debug.call_args[0][1] == list(subj.nid.keys())[0]
+        assert isinstance(x509.log.debug.call_args[0][2], TypeError)
 
     @skipIf(not HAS_M2CRYPTO, 'Skipping, M2Crypt is unavailble')
     def test_get_pem_entry(self):
-- 
2.19.0


++++++ x509-fixes-for-remote-signing-106.patch ++++++
>From 6276eb2cd3f2b396c13118a111998230477cc65a Mon Sep 17 00:00:00 2001
From: Florian Bergmann <bergma...@users.noreply.github.com>
Date: Tue, 11 Sep 2018 14:02:55 +0200
Subject: [PATCH] X509 fixes for remote signing (#106)

* Use to_str salt.utils when writing to a file.

* Assign the certificate as a string.

* Convert to string before sending via 'publish'.

Otherwise the publish call with receive a "b''" string, which can not be used
in the functions.

* Do not silently ignore errors.

At least log the occurring errors to debug and trace.
---
 salt/modules/x509.py | 10 +++++-----
 salt/states/x509.py  |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/salt/modules/x509.py b/salt/modules/x509.py
index 15de06e200..9901bc5bd9 100644
--- a/salt/modules/x509.py
+++ b/salt/modules/x509.py
@@ -658,7 +658,7 @@ def read_crl(crl):
     text = get_pem_entry(text, pem_type='X509 CRL')
 
     crltempfile = tempfile.NamedTemporaryFile()
-    crltempfile.write(text)
+    crltempfile.write(salt.utils.stringutils.to_str(text))
     crltempfile.flush()
     crlparsed = _parse_openssl_crl(crltempfile.name)
     crltempfile.close()
@@ -1368,9 +1368,9 @@ def create_certificate(
                 pem_type='CERTIFICATE REQUEST').replace('\n', '')
         if 'public_key' in kwargs:
             # Strip newlines to make passing through as cli functions easier
-            kwargs['public_key'] = get_public_key(
+            kwargs['public_key'] = 
salt.utils.stringutils.to_str(get_public_key(
                 kwargs['public_key'],
-                passphrase=kwargs['public_key_passphrase']).replace('\n', '')
+                passphrase=kwargs['public_key_passphrase'])).replace('\n', '')
 
         # Remove system entries in kwargs
         # Including listen_in and preqreuired because they are not included
@@ -1766,13 +1766,13 @@ def verify_crl(crl, cert):
     crltext = _text_or_file(crl)
     crltext = get_pem_entry(crltext, pem_type='X509 CRL')
     crltempfile = tempfile.NamedTemporaryFile()
-    crltempfile.write(crltext)
+    crltempfile.write(salt.utils.stringutils.to_str(crltext))
     crltempfile.flush()
 
     certtext = _text_or_file(cert)
     certtext = get_pem_entry(certtext, pem_type='CERTIFICATE')
     certtempfile = tempfile.NamedTemporaryFile()
-    certtempfile.write(certtext)
+    certtempfile.write(salt.utils.stringutils.to_str(certtext))
     certtempfile.flush()
 
     cmd = ('openssl crl -noout -in {0} -CAfile {1}'.format(
diff --git a/salt/states/x509.py b/salt/states/x509.py
index 832f74168c..7bb941f393 100644
--- a/salt/states/x509.py
+++ b/salt/states/x509.py
@@ -545,7 +545,7 @@ def certificate_managed(name,
             if not private_ret['result']:
                 return private_ret
 
-    file_args['contents'] += certificate
+    file_args['contents'] += salt.utils.stringutils.to_str(certificate)
 
     if not append_certs:
         append_certs = []
-- 
2.19.0



Reply via email to