<p dir="auto">From <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/schwatvogel/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/schwatvogel">@schwatvogel</a> on 2016-09-30T12:52:18Z</p>
<h5 dir="auto">ISSUE TYPE</h5>
<ul dir="auto">
<li>Bug Report</li>
</ul>
<h5 dir="auto">COMPONENT NAME</h5>
<p dir="auto">ansible-modules-core/packaging/os/rpm_key.py</p>
<h5 dir="auto">ANSIBLE VERSION</h5>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="ansible 2.1.0.0"><pre class="notranslate"><code class="notranslate">ansible 2.1.0.0
</code></pre></div>
<h5 dir="auto">CONFIGURATION</h5>
<p dir="auto">not relevant</p>
<h5 dir="auto">OS / ENVIRONMENT</h5>
<p dir="auto">N/A<br>
Redhat/Centos rpm-based</p>
<h5 dir="auto">SUMMARY</h5>
<p dir="auto">Function is_key_imported does not work reliably because<br>
Function getkeyid only extracts the last part of the first signature packet,<br>
therefore the key will be imported on every ansible run</p>
<h5 dir="auto">STEPS TO REPRODUCE</h5>
<p dir="auto">Install the Mono gpg key (from the Ubuntu keyserver, as per official docu):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="http://keyserver.ubuntu.com/pks/lookup?op=get&amp;search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF"><pre class="notranslate"><code class="notranslate">http://keyserver.ubuntu.com/pks/lookup?op=get&amp;search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
</code></pre></div>
<p dir="auto">Short Summary:<br>
<code class="notranslate">getkeyid()</code> essentially runs<br>
<code class="notranslate">gpg --no-tty --batch --with-colons --fixed-list-mode --list-packets /tmp/key.1 |grep signature</code><br>
And returns the last 8 characters of the first key id it finds.</p>
<p dir="auto">Then <code class="notranslate">is_key_imported()</code>  runs<br>
<code class="notranslate">rpm -qa gpg-pubkey</code> and matches the keyid against the first key part of the filename:<br>
gpg-pubkey-<strong>d3d831ef</strong>-53dfa827</p>
<p dir="auto">This does'nt work with the Mono key because<br>
<code class="notranslate">gpg --no-tty --batch --with-colons --fixed-list-mode --list-packets /tmp/key.1 |grep signature</code><br>
returns:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content=":signature packet: algo 1, keyid C90F9CB90E1FAD0C
:signature packet: algo 1, keyid A6A19B38D3D831EF
:signature packet: algo 1, keyid A6A19B38D3D831EF"><pre class="notranslate"><code class="notranslate">:signature packet: algo 1, keyid C90F9CB90E1FAD0C
:signature packet: algo 1, keyid A6A19B38D3D831EF
:signature packet: algo 1, keyid A6A19B38D3D831EF
</code></pre></div>
<p dir="auto">and so the last 8 characters of the second keyid match the first 8 character set of the rpm key information</p>
<p dir="auto">Perhaps verifying the Fingerprint of the keys, or verify the full key ids(patch following):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="--- rpm_key.py  2016-09-30 13:38:31.000000000 +0200
+++ new_rpm_key.py  2016-09-30 14:49:18.000000000 +0200
@@ -149,33 +149,27 @@
         stdout, stderr = self.execute_command([gpg, '--no-tty', '--batch', '--with-colons', '--fixed-list-mode', '--list-packets', keyfile])
         for line in stdout.splitlines():
             line = line.strip()
-            if line.startswith(':signature packet:'):
-                # We want just the last 8 characters of the keyid
-                keyid = line.split()[-1].strip()[8:]
+            if &quot;keyid:&quot; in line:
+                keyid = line.split()[-1]
                 return keyid
         self.json_fail(msg=&quot;Unexpected gpg output&quot;)

     def is_keyid(self, keystr):
         &quot;&quot;&quot;Verifies if a key, as provided by the user is a keyid&quot;&quot;&quot;
-        return re.match('(0x)?[0-9a-f]{8}', keystr, flags=re.IGNORECASE)
+        return re.match('(0x)?[0-9a-f]{16}', keystr, flags=re.IGNORECASE)

     def execute_command(self, cmd):
-        rc, stdout, stderr = self.module.run_command(cmd)
+        rc, stdout, stderr = self.module.run_command(cmd,use_unsafe_shell=True)
         if rc != 0:
             self.module.fail_json(msg=stderr)
         return stdout, stderr

     def is_key_imported(self, keyid):
-        stdout, stderr = self.execute_command([self.rpm, '-qa', 'gpg-pubkey'])
+        cmd=self.rpm+' -q  gpg-pubkey --qf &quot;%{description}&quot; | gpg --no-tty --batch --with-colons --fixed-list-mode --list-packets -'
+        stdout, stderr = self.execute_command(cmd)
         for line in stdout.splitlines():
-            line = line.strip()
-            if not line:
-                continue
-            match = re.match('gpg-pubkey-([0-9a-f]+)-([0-9a-f]+)', line)
-            if not match:
-                self.module.fail_json(msg=&quot;rpm returned unexpected output [%s]&quot; % line)
-            else:
-                if keyid == match.group(1):
+            if &quot;keyid: &quot; in line:
+                if keyid.upper() == line.split()[-1].upper():
                     return True
         return False```"><pre class="notranslate"><code class="notranslate">--- rpm_key.py  2016-09-30 13:38:31.000000000 +0200
+++ new_rpm_key.py  2016-09-30 14:49:18.000000000 +0200
@@ -149,33 +149,27 @@
         stdout, stderr = self.execute_command([gpg, '--no-tty', '--batch', '--with-colons', '--fixed-list-mode', '--list-packets', keyfile])
         for line in stdout.splitlines():
             line = line.strip()
-            if line.startswith(':signature packet:'):
-                # We want just the last 8 characters of the keyid
-                keyid = line.split()[-1].strip()[8:]
+            if "keyid:" in line:
+                keyid = line.split()[-1]
                 return keyid
         self.json_fail(msg="Unexpected gpg output")

     def is_keyid(self, keystr):
         """Verifies if a key, as provided by the user is a keyid"""
-        return re.match('(0x)?[0-9a-f]{8}', keystr, flags=re.IGNORECASE)
+        return re.match('(0x)?[0-9a-f]{16}', keystr, flags=re.IGNORECASE)

     def execute_command(self, cmd):
-        rc, stdout, stderr = self.module.run_command(cmd)
+        rc, stdout, stderr = self.module.run_command(cmd,use_unsafe_shell=True)
         if rc != 0:
             self.module.fail_json(msg=stderr)
         return stdout, stderr

     def is_key_imported(self, keyid):
-        stdout, stderr = self.execute_command([self.rpm, '-qa', 'gpg-pubkey'])
+        cmd=self.rpm+' -q  gpg-pubkey --qf "%{description}" | gpg --no-tty --batch --with-colons --fixed-list-mode --list-packets -'
+        stdout, stderr = self.execute_command(cmd)
         for line in stdout.splitlines():
-            line = line.strip()
-            if not line:
-                continue
-            match = re.match('gpg-pubkey-([0-9a-f]+)-([0-9a-f]+)', line)
-            if not match:
-                self.module.fail_json(msg="rpm returned unexpected output [%s]" % line)
-            else:
-                if keyid == match.group(1):
+            if "keyid: " in line:
+                if keyid.upper() == line.split()[-1].upper():
                     return True
         return False```
</code></pre></div>
<p dir="auto">Copied from original issue: <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="180296600" data-permission-text="Title is private" data-url="https://github.com/ansible/ansible-modules-core/issues/5103" data-hovercard-type="issue" data-hovercard-url="/ansible/ansible-modules-core/issues/5103/hovercard" href="https://github.com/ansible/ansible-modules-core/issues/5103">ansible/ansible-modules-core#5103</a></p>
<h5 dir="auto">ISSUE TYPE</h5>
<ul dir="auto">
<li>Bug Report</li>
</ul>
<h5 dir="auto">COMPONENT NAME</h5>
<p dir="auto">ansible/modules/packaging/os/rpm_key.py</p>
<h5 dir="auto">ANSIBLE VERSION</h5>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="ansible 2.2.1.0"><pre class="notranslate"><code class="notranslate">ansible 2.2.1.0
</code></pre></div>
<h5 dir="auto">CONFIGURATION</h5>
<p dir="auto">not relevant</p>
<h5 dir="auto">OS / ENVIRONMENT</h5>
<p dir="auto">N/A<br>
Redhat/Centos rpm-based</p>
<h5 dir="auto">SUMMARY</h5>
<p dir="auto">Function is_key_imported does not work reliably because<br>
Function getkeyid only extracts the last part of the first signature packet,ignoring the significant other ids<br>
therefore the key will be imported on every ansible run</p>
<h5 dir="auto">STEPS TO REPRODUCE</h5>
<p dir="auto">Install the Mono gpg key (from the Ubuntu keyserver, as per official docu):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="http://keyserver.ubuntu.com/pks/lookup?op=get&amp;search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF"><pre class="notranslate"><code class="notranslate">http://keyserver.ubuntu.com/pks/lookup?op=get&amp;search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
</code></pre></div>
<h6 dir="auto">Short Summary:</h6>
<p dir="auto"><code class="notranslate">getkeyid()</code> essentially runs<br>
<code class="notranslate">gpg --no-tty --batch --with-colons --fixed-list-mode --list-packets /tmp/key.1 |grep signature</code><br>
And returns the last 8 characters of the first key id it finds:<br>
<code class="notranslate">90E1FAD0C</code><br>
instead of all keyids in this package:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="C90F9CB90E1FAD0C
01150A655BBD8102
A6A19B38D3D831EF
A6A19B38D3D831EF"><pre class="notranslate"><code class="notranslate">C90F9CB90E1FAD0C
01150A655BBD8102
A6A19B38D3D831EF
A6A19B38D3D831EF
</code></pre></div>
<p dir="auto">Then <code class="notranslate">is_key_imported()</code>  runs<br>
<code class="notranslate">rpm -qa gpg-pubkey</code> and matches the keyid against the first key part of the filename:<br>
gpg-pubkey-<strong>d3d831ef</strong>-53dfa827</p>
<p dir="auto">This does'nt work with the Mono key because the partial keyid in the filename is from the second keyid in the key</p>
<h5 dir="auto">Possible Solutions:</h5>
<p dir="auto">Perhaps verifying the Fingerprint of the keys, or<br>
verify the full key ids:<br>
Fetching the full 16 Character key-ids (all of them not just the first)<br>
and verify them against all installed key ids (not just rpm names)<br>
by listing all installed gpgkeys and extracting the keyids in the same way, as the are extracted from the reference keys:<br>
<code class="notranslate">rpm -qa gpg-pubkey --qf "%{description}"| gpg --no-tty --batch --with-colons --fixed-list-mode --list-packets -</code></p>