Bug 1572142 - Intermittent Exception: nss cert db creation command failed to complete r=tarek

Differential Revision: https://phabricator.services.mozilla.com/D45163

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Florin Strugariu 2019-09-18 09:15:14 +00:00
Родитель 68a8d951e4
Коммит b4b1cbd754
1 изменённых файлов: 59 добавлений и 62 удалений

Просмотреть файл

@ -10,6 +10,7 @@ import subprocess
import sys
import time
import socket
from subprocess import PIPE
import mozinfo
from mozprocess import ProcessHandler
@ -201,9 +202,9 @@ class Mitmproxy(Playback):
command.extend(self.config["playback_tool_args"])
elif "playback_files" in self.config:
script = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "scripts",
"alternate-server-replay-{}.py".format(
self.config["playback_version"]))
os.path.dirname(os.path.realpath(__file__)), "scripts",
"alternate-server-replay-{}.py".format(
self.config["playback_version"]))
recording_paths = self.config["playback_files"]
# this part is platform-specific
if mozinfo.os == "win":
@ -393,11 +394,6 @@ class MitmproxyDesktop(Mitmproxy):
class MitmproxyAndroid(Mitmproxy):
@property
def certutil_sleep_seconds(self):
"""Time to sleep, in seconds, after issuing a `certutil` command."""
return 10 if not self.config["run_local"] else 1
def setup(self):
self.download_and_install_host_utils()
self.install_mitmproxy_cert(self.browser_path)
@ -413,13 +409,13 @@ class MitmproxyAndroid(Mitmproxy):
"""
if self.config["run_local"]:
# when running locally, it is found in the Firefox desktop build (..obj../dist/bin)
self.certutil = os.path.join(os.environ["MOZ_HOST_BIN"], "certutil")
self.certutil_path = os.path.join(os.environ["MOZ_HOST_BIN"], "certutil")
if not (
os.path.isfile(self.certutil) and os.access(self.certutil, os.X_OK)
os.path.isfile(self.certutil_path) and os.access(self.certutil_path, os.X_OK)
):
raise Exception("Abort: unable to execute certutil: {}".format(self.certutil))
self.certutil = os.environ["MOZ_HOST_BIN"]
os.environ["LD_LIBRARY_PATH"] = self.certutil
raise Exception("Abort: unable to execute certutil: {}".format(self.certutil_path))
self.certutil_path = os.environ["MOZ_HOST_BIN"]
os.environ["LD_LIBRARY_PATH"] = self.certutil_path
else:
# must download certutil inside hostutils via tooltool; use this manifest:
# mozilla-central/testing/config/tooltool-manifests/linux64/hostutils.manifest
@ -457,19 +453,19 @@ class MitmproxyAndroid(Mitmproxy):
tooltool_download(_dest, self.config["run_local"], self.mozproxy_dir)
# the production bitbar container host is always linux
self.certutil = glob.glob(
self.certutil_path = glob.glob(
os.path.join(self.mozproxy_dir, "host-utils*[!z|checksum]")
)[0]
# must add hostutils/certutil to the path
os.environ["LD_LIBRARY_PATH"] = self.certutil
os.environ["LD_LIBRARY_PATH"] = self.certutil_path
bin_suffix = mozinfo.info.get("bin_suffix", "")
self.certutil = os.path.join(self.certutil, "certutil" + bin_suffix)
if os.path.isfile(self.certutil):
LOG.info("certutil is found at: %s" % self.certutil)
self.certutil_path = os.path.join(self.certutil_path, "certutil" + bin_suffix)
if os.path.isfile(self.certutil_path):
LOG.info("certutil is found at: %s" % self.certutil_path)
else:
raise Exception("unable to find certutil at %s" % self.certutil)
raise Exception("unable to find certutil at %s" % self.certutil_path)
def install_mitmproxy_cert(self, browser_path):
"""Install the CA certificate generated by mitmproxy, into geckoview android
@ -498,8 +494,7 @@ class MitmproxyAndroid(Mitmproxy):
def import_certificate_in_cert_db(self, cert_db_location, local_cert_path):
# import mitmproxy cert into the db
command = [
self.certutil,
args = [
"-A",
"-d",
cert_db_location,
@ -511,31 +506,20 @@ class MitmproxyAndroid(Mitmproxy):
"-i",
local_cert_path,
]
LOG.info(
"importing mitmproxy cert into db using command: %s" % " ".join(command)
"importing mitmproxy cert into db using command"
)
cmd_proc = subprocess.Popen(command, env=os.environ.copy())
time.sleep(self.certutil_sleep_seconds)
cmd_terminated = cmd_proc.poll()
if cmd_terminated is None: # None value indicates process hasn't terminated
LOG.critical(
"command to import mitmproxy cert into cert db failed to complete"
)
self.certutil(args)
def create_cert_db(self, cert_db_location):
# create cert db if it doesn't already exist; it may exist already
# if a previous pageload test ran in the same test suite
command = [self.certutil, "-d", cert_db_location, "-N", "--empty-password"]
args = ["-d", cert_db_location, "-N", "--empty-password"]
LOG.info("creating nss cert database")
self.certutil(args)
LOG.info("creating nss cert database using command: %s" % " ".join(command))
cmd_proc = subprocess.Popen(command, env=os.environ.copy())
time.sleep(self.certutil_sleep_seconds)
cmd_terminated = cmd_proc.poll()
if cmd_terminated is None: # None value indicates process hasn't terminated
raise Exception("nss cert db creation command failed to complete")
if not self.cert_db_exists(cert_db_location):
raise Exception("nss cert db creation command failed. Cert db not created.")
@ -544,21 +528,16 @@ class MitmproxyAndroid(Mitmproxy):
LOG.info(
"checking if the nss cert db already exists in the android browser profile"
)
command = [self.certutil, "-d", cert_db_location, "-L"]
try:
subprocess.check_call(command, env=os.environ.copy())
args = ["-d", cert_db_location, "-L"]
cert_db_exists = self.certutil(args, raise_exception=False)
if cert_db_exists:
LOG.info("the nss cert db exists")
cert_db_exists = True
except subprocess.CalledProcessError:
# this means the nss cert db doesn't exist yet
LOG.info("nss cert db doesn't exist yet. Note: certutil error is expected!!!")
cert_db_exists = False
# try a forced pause between certutil cmds; possibly reduce later
time.sleep(self.certutil_sleep_seconds)
return cert_db_exists
return True
else:
LOG.info("nss cert db doesn't exist yet.")
return False
def is_mitmproxy_cert_installed(self, cert_db_location):
"""Verify mitmxproy CA cert was added to Firefox on android"""
@ -568,21 +547,39 @@ class MitmproxyAndroid(Mitmproxy):
LOG.info(
"getting the list of certs in the nss cert db in the android browser profile"
)
command = [self.certutil, "-d", cert_db_location, "-L"]
args = ["-d", cert_db_location, "-L"]
try:
cmd_output = subprocess.check_output(command, env=os.environ.copy())
except subprocess.CalledProcessError:
# cmd itself failed
LOG.error(cmd_output)
raise Exception("certutil command failed")
cmd_output = self.certutil(args)
# check output from the certutil command, see if 'mitmproxy-cert' is listed
time.sleep(self.certutil_sleep_seconds)
LOG.info(cmd_output)
if "mitmproxy-cert" in cmd_output:
LOG.info(
"verfied the mitmproxy-cert is installed in the nss cert db on android"
)
return True
return False
def certutil(self, args, raise_exception=True):
cmd = [self.certutil_path] + list(args)
LOG.info("Certutil: Running command: %s" % " ".join(cmd))
try:
cmd_proc = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE, env=os.environ.copy())
cmd_output, errs = cmd_proc.communicate()
except subprocess.SubprocessError:
LOG.critical("could not run the certutil command")
raise
if cmd_proc.returncode == 0:
# Debug purpose only remove if stable
LOG.info("Certutil returncode: %s" % cmd_proc.returncode)
LOG.info("Certutil output: %s" % cmd_output)
return cmd_output
else:
if raise_exception:
LOG.critical("Certutil command failed!!")
LOG.info("Certutil returncode: %s" % cmd_proc.returncode)
LOG.info("Certutil output: %s" % cmd_output)
LOG.info("Certutil error: %s" % errs)
raise Exception("Certutil command failed!!")
else:
return False