From 46b817b8c7e7d66ee91f9f47c00e96d5afa8a18e Mon Sep 17 00:00:00 2001
From: Kyle Lape <klape@redhat.com>
Date: Fri, 23 Feb 2018 12:52:04 -0600
Subject: [PATCH] GPG verify egg in parent process
This fixes issue #54.
- Add GPG verification code (instead of relying on code from egg)
- Enable bypass via environment variable BYPASS_GPG. The process only
recognizes the value "true" (case insensitive); all other values resolve
to false. This only applies to the GPG verification done in the parent
process; eggs loaded in subprocess (i.e. phases) still use --no-gpg.
- If last_stable.egg cannot be GPG verified, try rpm.egg. If rpm.egg is
verified, use it instead of last_stable.egg. If rpm.egg cannot be
verified, either, then print an error message and exit.
- A debug logging statement is added after logging has been set up to
indicate which egg was loaded in the parent process.
Look for string: "Loaded initial egg".
---
insights_client/__init__.py | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/insights_client/__init__.py b/insights_client/__init__.py
index d8932f5..fd2adf0 100644
--- a/insights_client/__init__.py
+++ b/insights_client/__init__.py
@@ -9,9 +9,14 @@ import grp
import os
import sys
import subprocess
+from subprocess import PIPE
+import shlex
import logging
import logging.handlers
+GPG_KEY = "/etc/insights-client/redhattools.pub.gpg"
+
+BYPASS_GPG = os.environ.get("BYPASS_GPG", "").lower() == "true"
ENV_EGG = os.environ.get("EGG")
NEW_EGG = "/var/lib/insights/newest.egg"
STABLE_EGG = "/var/lib/insights/last_stable.egg"
@@ -44,6 +49,17 @@ def demote(uid, gid, run_as_root):
return result
+def gpg_validate(path):
+ if BYPASS_GPG:
+ return True
+
+ gpg_template = '/usr/bin/gpg --verify --keyring %s %s %s'
+ cmd = gpg_template % (GPG_KEY, path + '.asc', path)
+ proc = subprocess.Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)
+ proc.communicate()
+ return proc.returncode == 0
+
+
def run_phase(phase, client):
"""
Call the run script for the given phase. If the phase succeeds returns the
@@ -106,10 +122,16 @@ def _main():
if not all(map(None, [insights_uid, insights_gid, insights_grpid])):
sys.exit("User and/or group 'insights' not found. Exiting.")
- sys.path = [STABLE_EGG, RPM_EGG] + sys.path
+ validated_eggs = filter(gpg_validate, [STABLE_EGG, RPM_EGG])
+
+ if not validated_eggs:
+ sys.exit("No GPG-verified eggs can be found")
+
+ sys.path = validated_eggs + sys.path
try:
# flake8 complains because these imports aren't at the top
+ import insights
from insights.client import InsightsClient
from insights.client.phase.v1 import get_phases
@@ -124,6 +146,7 @@ def _main():
log_handler.doRollover()
# we now have access to the clients logging mechanism instead of using print
client.set_up_logging()
+ logging.root.debug("Loaded initial egg: %s", os.path.dirname(insights.__file__))
# check for insights user/group
if not (insights_uid or insights_gid):
--
2.14.3