summaryrefslogtreecommitdiffstats
path: root/testing/mozbase/mozproxy/mozproxy/backends/mitm/desktop.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mozbase/mozproxy/mozproxy/backends/mitm/desktop.py')
-rw-r--r--testing/mozbase/mozproxy/mozproxy/backends/mitm/desktop.py161
1 files changed, 161 insertions, 0 deletions
diff --git a/testing/mozbase/mozproxy/mozproxy/backends/mitm/desktop.py b/testing/mozbase/mozproxy/mozproxy/backends/mitm/desktop.py
new file mode 100644
index 0000000000..f9c30c9b0e
--- /dev/null
+++ b/testing/mozbase/mozproxy/mozproxy/backends/mitm/desktop.py
@@ -0,0 +1,161 @@
+"""Functions to download, install, setup, and use the mitmproxy playback tool"""
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+import os
+import sys
+
+import mozinfo
+
+from mozproxy.backends.mitm.mitm import Mitmproxy
+from mozproxy.utils import LOG
+
+# to install mitmproxy certificate into Firefox and turn on/off proxy
+POLICIES_CONTENT_ON = """{
+ "policies": {
+ "Certificates": {
+ "Install": ["%(cert)s"]
+ },
+ "Proxy": {
+ "Mode": "manual",
+ "HTTPProxy": "%(host)s:%(port)d",
+ "SSLProxy": "%(host)s:%(port)d",
+ "Passthrough": "%(host)s",
+ "Locked": true
+ }
+ }
+}"""
+
+POLICIES_CONTENT_OFF = """{
+ "policies": {
+ "Proxy": {
+ "Mode": "none",
+ "Locked": false
+ }
+ }
+}"""
+
+# path for mitmproxy certificate, generated auto after mitmdump is started
+# on local machine it is 'HOME', however it is different on production machines
+try:
+ DEFAULT_CERT_PATH = os.path.join(
+ os.getenv("HOME"), ".mitmproxy", "mitmproxy-ca-cert.cer"
+ )
+except Exception:
+ DEFAULT_CERT_PATH = os.path.join(
+ os.getenv("HOMEDRIVE"),
+ os.getenv("HOMEPATH"),
+ ".mitmproxy",
+ "mitmproxy-ca-cert.cer",
+ )
+
+# On Windows, deal with mozilla-build having forward slashes in $HOME:
+if os.name == "nt" and "/" in DEFAULT_CERT_PATH:
+ DEFAULT_CERT_PATH = DEFAULT_CERT_PATH.replace("/", "\\")
+
+
+class MitmproxyDesktop(Mitmproxy):
+ def setup(self):
+ """
+ Installs certificates.
+
+ For Firefox we need to install the generated mitmproxy CA cert. For
+ Chromium this is not necessary as it will be started with the
+ --ignore-certificate-errors cmd line arg.
+ """
+ if not self.config["app"] == "firefox":
+ return
+ # install the generated CA certificate into Firefox desktop
+ self.install_mitmproxy_cert(self.browser_path)
+
+ def install_mitmproxy_cert(self, browser_path):
+ """Install the CA certificate generated by mitmproxy, into Firefox
+ 1. Create a dir called 'distribution' in the same directory as the Firefox executable
+ 2. Create the policies.json file inside that folder; which points to the certificate
+ location, and turns on the the browser proxy settings
+ """
+ LOG.info("Installing mitmproxy CA certficate into Firefox")
+
+ # browser_path is the exe, we want the folder
+ self.policies_dir = os.path.dirname(browser_path)
+ # on macosx we need to remove the last folders 'MacOS'
+ # and the policies json needs to go in ../Content/Resources/
+ if "mac" in self.config["platform"]:
+ self.policies_dir = os.path.join(self.policies_dir[:-6], "Resources")
+ # for all platforms the policies json goes in a 'distribution' dir
+ self.policies_dir = os.path.join(self.policies_dir, "distribution")
+
+ self.cert_path = DEFAULT_CERT_PATH
+ # for windows only
+ if mozinfo.os == "win":
+ self.cert_path = self.cert_path.replace("\\", "\\\\")
+
+ if not os.path.exists(self.policies_dir):
+ LOG.info("creating folder: %s" % self.policies_dir)
+ os.makedirs(self.policies_dir)
+ else:
+ LOG.info("folder already exists: %s" % self.policies_dir)
+
+ self.write_policies_json(
+ self.policies_dir,
+ policies_content=POLICIES_CONTENT_ON
+ % {"cert": self.cert_path, "host": self.host, "port": self.port},
+ )
+
+ # cannot continue if failed to add CA cert to Firefox, need to check
+ if not self.is_mitmproxy_cert_installed():
+ LOG.error(
+ "Aborting: failed to install mitmproxy CA cert into Firefox desktop"
+ )
+ self.stop_mitmproxy_playback()
+ sys.exit()
+
+ def write_policies_json(self, location, policies_content):
+ policies_file = os.path.join(location, "policies.json")
+ LOG.info("writing: %s" % policies_file)
+
+ with open(policies_file, "w") as fd:
+ fd.write(policies_content)
+
+ def read_policies_json(self, location):
+ policies_file = os.path.join(location, "policies.json")
+ LOG.info("reading: %s" % policies_file)
+
+ with open(policies_file, "r") as fd:
+ return fd.read()
+
+ def is_mitmproxy_cert_installed(self):
+ """Verify mitmxproy CA cert was added to Firefox"""
+ try:
+ # read autoconfig file, confirm mitmproxy cert is in there
+ contents = self.read_policies_json(self.policies_dir)
+ LOG.info("Firefox policies file contents:")
+ LOG.info(contents)
+ if (
+ POLICIES_CONTENT_ON
+ % {"cert": self.cert_path, "host": self.host, "port": self.port}
+ ) in contents:
+ LOG.info("Verified mitmproxy CA certificate is installed in Firefox")
+ else:
+
+ return False
+ except Exception as e:
+ LOG.info("failed to read Firefox policies file, exeption: %s" % e)
+ return False
+ return True
+
+ def stop(self):
+ LOG.info("MitmproxyDesktop stop!!")
+ super(MitmproxyDesktop, self).stop()
+ self.turn_off_browser_proxy()
+
+ def turn_off_browser_proxy(self):
+ """Turn off the browser proxy that was used for mitmproxy playback. In Firefox
+ we need to change the autoconfig files to revert the proxy; for Chromium the proxy
+ was setup on the cmd line, so nothing is required here."""
+ if self.config["app"] == "firefox" and self.policies_dir is not None:
+ LOG.info("Turning off the browser proxy")
+
+ self.write_policies_json(
+ self.policies_dir, policies_content=POLICIES_CONTENT_OFF
+ )