Diff
Modified: trunk/Tools/ChangeLog (229540 => 229541)
--- trunk/Tools/ChangeLog 2018-03-12 17:53:39 UTC (rev 229540)
+++ trunk/Tools/ChangeLog 2018-03-12 18:05:36 UTC (rev 229541)
@@ -1,3 +1,38 @@
+2018-03-12 Basuke Suzuki <[email protected]>
+
+ [webkitpy] Remove openssl command dependency.
+ https://bugs.webkit.org/show_bug.cgi?id=183494
+
+ Reviewed by Ryosuke Niwa.
+
+ Added Python implementation of PEM file perser and switched to use that
+ from external `openssl` command.
+
+ * Scripts/webkitpy/common/system/pemfile.py: Added.
+ (load):
+ (BadFormatError):
+ (Pem):
+ (Pem.__init__):
+ (Pem.get):
+ (Pem.get_all):
+ (Pem.certificate):
+ (Pem.private_key):
+ (Pem.csr):
+ (Pem.certificate_request):
+ (Pem.certificate_signing_request):
+ (_parse_pem_format):
+ (_parse_pem_format.find_begin):
+ (_parse_pem_format.find_end):
+ (_parse_pem_format.sections):
+ * Scripts/webkitpy/common/system/pemfile_unittest.py: Added.
+ (PemFileTest):
+ (PemFileTest.test_parse):
+ (PemFileTest.test_parse_bad_format):
+ * Scripts/webkitpy/port/base.py:
+ (Port.start_websocket_server):
+ (Port._extract_certificate_from_pem): Deleted.
+ (Port._extract_private_key_from_pem): Deleted.
+
2018-03-12 Javier Fernandez <[email protected]>
Remove GridLayout runtime flag
Added: trunk/Tools/Scripts/webkitpy/common/system/pemfile.py (0 => 229541)
--- trunk/Tools/Scripts/webkitpy/common/system/pemfile.py (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/system/pemfile.py 2018-03-12 18:05:36 UTC (rev 229541)
@@ -0,0 +1,139 @@
+# Copyright (C) 2018 Sony Interactive Entertainment Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+import re
+
+
+def load(filesystem, path):
+ """Load PEM file and return PEM object"""
+ return Pem(filesystem.read_text_file(path))
+
+
+class BadFormatError(Exception):
+ """Bad format error"""
+ pass
+
+
+class Pem(object):
+ """
+ Container for certificate related information.
+ Each section in PEM file can be accessible by get().
+ e.g.
+ pem = pemfile.load(filesystem, "/path/to/sample.pem")
+ assert pem.certificate.startswith("-----BEGIN CERTIFICATE-----")
+ """
+
+ def __init__(self, content):
+ self._contents = _parse_pem_format(content)
+ if not self._contents:
+ raise BadFormatError("Cannot find any sections in this file.")
+
+ def get(self, kind):
+ """Return requested information or None if not found."""
+ items = self.get_all(kind)
+ if not items:
+ raise KeyError("{} is not in this PEM".format(kind))
+ return items[0]
+
+ def get_all(self, kind):
+ """Return all matching requested information"""
+ return [content for (key, content) in self._contents if key == kind]
+
+ @property
+ def certificate(self):
+ """Return certificate"""
+ return self.get(CERTIFICATE)
+
+ @property
+ def private_key(self):
+ """Return private key"""
+ return self.get(RSA_PRIVATE_KEY)
+
+ @property
+ def csr(self):
+ """Return certificate request"""
+ return self.get(CERTIFICATE_REQUEST)
+
+ @property
+ def certificate_request(self):
+ """Alias for csr()"""
+ return self.csr
+
+ @property
+ def certificate_signing_request(self):
+ """Alias for csr()"""
+ return self.csr
+
+
+MARKER = "-----"
+BEGIN_MARKER = "BEGIN "
+END_MARKER = "END"
+
+CERTIFICATE_REQUEST = "CERTIFICATE REQUEST"
+RSA_PRIVATE_KEY = "RSA PRIVATE KEY"
+CERTIFICATE = "CERTIFICATE"
+
+BEGIN_PATTERN = re.compile("^{}BEGIN (.+){}$".format(MARKER, MARKER))
+
+
+def _parse_pem_format(content):
+ lines = content.split("\n")
+
+ def find_begin(lines):
+ """
+ Find first matching BEGIN marker.
+ @returns found key and rest of lines | None
+ """
+ while lines:
+ matched = BEGIN_PATTERN.match(lines[0])
+ if matched:
+ return (matched.group(1), lines)
+ lines = lines[1:]
+ return None
+
+ def find_end(kind, lines):
+ """
+ Find END marker.
+ @returns key, found contents and rest of lines.
+ @raise BadFormatError
+ """
+ end_marker = "{}END {}{}".format(MARKER, kind, MARKER)
+
+ try:
+ index = lines.index(end_marker)
+ except ValueError, e:
+ raise BadFormatError("Cannot find section end: {}".format(end_marker))
+
+ return kind, "\n".join(lines[0:index + 1]) + "\n", lines[index + 1:]
+
+ def sections(lines):
+ """Section Generator"""
+ while lines:
+ result = find_begin(lines)
+ if not result:
+ break
+ key, body, lines = find_end(*result)
+ yield (key, body)
+
+ return [section for section in sections(lines)]
Added: trunk/Tools/Scripts/webkitpy/common/system/pemfile_unittest.py (0 => 229541)
--- trunk/Tools/Scripts/webkitpy/common/system/pemfile_unittest.py (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/system/pemfile_unittest.py 2018-03-12 18:05:36 UTC (rev 229541)
@@ -0,0 +1,164 @@
+# Copyright (C) 2018 Sony Interactive Entertainment Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+import unittest
+import sys
+
+from webkitpy.common.system.pemfile import Pem, BadFormatError
+
+
+class PemFileTest(unittest.TestCase):
+ """Test Pem file parsing"""
+ def test_parse(self):
+ pem = Pem(self.pem_contents)
+
+ self.assertEqual(pem.private_key, self.private_key)
+ self.assertEqual(pem.certificate, self.certificate)
+
+ with self.assertRaises(KeyError):
+ pem.csr
+
+ with self.assertRaises(KeyError):
+ pem.get("FOO BAR")
+
+ def test_parse_bad_format(self):
+ with self.assertRaises(BadFormatError):
+ # Partial contents raises format error
+ Pem(trim("""-----BEGIN RSA PRIVATE KEY-----
+ MIICXQIBAAKBgQCmcXbusrr8zQr8snIb0OVQibVfgv7zPjh/5xdcrKOejJzp3epA
+ AF4TITeFR9vzWIwkmkcRoY+IbQNhh7kefGUYD47bvVamJMtq5cGYVs0HngT+KTMa
+ NGH/G44KkFIOaz/b5d/JNKONrlqwxqXS+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQAB
+ """) + "\n")
+
+ with self.assertRaises(BadFormatError):
+ # No section content raises format error
+ Pem("""HELLO WORLD
+ HOW'S GOING????
+ """)
+
+ def test_parse_custom_content(self):
+ pem = Pem(trim("""Hi, please take this.
+ -----BEGIN FOOBAR-----
+ HELLO/WORKD===
+ -----END FOOBAR-----
+ regards,
+ kind of mail signature comes here
+ """) + "\n")
+
+ self.assertEqual(
+ trim(pem.get("FOOBAR")),
+ trim("""-----BEGIN FOOBAR-----
+ HELLO/WORKD===
+ -----END FOOBAR-----"""))
+
+ def setUp(self):
+ self.pem_contents = trim("""-----BEGIN RSA PRIVATE KEY-----
+ MIICXQIBAAKBgQCmcXbusrr8zQr8snIb0OVQibVfgv7zPjh/5xdcrKOejJzp3epA
+ AF4TITeFR9vzWIwkmkcRoY+IbQNhh7kefGUYD47bvVamJMtq5cGYVs0HngT+KTMa
+ NGH/G44KkFIOaz/b5d/JNKONrlqwxqXS+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQAB
+ AoGBAIcDv4A9h6UOBv2ZGyspNvsv2erSblGOhXJrWO4aNNemJJspIp4sLiPCbDE3
+ a1po17XRWBkbPz1hgL6axDXQnoeo++ebfrvRSed+Fys4+6SvuSrPOv6PmWTBT/Wa
+ GpO+tv48JUNxC/Dy8ROixBXOViuIBEFq3NfVH4HU3+RG20NhAkEA1L3RAhdfPkLI
+ 82luSOYE3Eq44lICb/yZi+JEihwSeZTJKdZHwYD8KVCjOtjGrOmyEyvThrcIACQz
+ JLEreVh33wJBAMhJm9pzJJNkIyBgiXA66FAwbhdDzSTPx0OBjoVWoj6u7jzGvIFT
+ Cn1aiTBYzzsiMCaCx+W3e6pK/DcvHSwKrgkCQHZMcxwBmSHLC2lnmD8LQWqqVnLr
+ fZV+VnfVw501DQT0uoP8NvygWBg1Uf9YKepfLXnBpidEQjup5ZKivnUEv+sCQA8N
+ 6VcMHI2vkyxV1T7ITrnoSf4ZrIu9yl56mHnRPzSy9VlAHt8hnMI7UeB+bGUndrMO
+ VXQgzHzKUhbbxbePvfECQQDTtkOuhJyKDfHCxLDcwNpi+T6OWTEfCw/cq9ZWDbA7
+ yCX81pQxfZkfMIS1YFIOGHovK0rMMTraCe+iDNYtVz/L
+ -----END RSA PRIVATE KEY-----
+ -----BEGIN CERTIFICATE-----
+ MIIB9zCCAWACCQDjWWTeC6BQvTANBgkqhkiG9w0BAQQFADBAMQswCQYDVQQGEwJB
+ VTETMBEGA1UECBMKU29tZS1TdGF0ZTEcMBoGA1UEChMTV2ViS2l0IExheW91dCBU
+ ZXN0czAeFw0wNzA3MTMxMjUxMzJaFw03MTA1MTMwNjIzMTZaMEAxCzAJBgNVBAYT
+ AkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRwwGgYDVQQKExNXZWJLaXQgTGF5b3V0
+ IFRlc3RzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmcXbusrr8zQr8snIb
+ 0OVQibVfgv7zPjh/5xdcrKOejJzp3epAAF4TITeFR9vzWIwkmkcRoY+IbQNhh7ke
+ fGUYD47bvVamJMtq5cGYVs0HngT+KTMaNGH/G44KkFIOaz/b5d/JNKONrlqwxqXS
+ +m6IY4l/E1Ff25ZjND5TaEvI1wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAAfbUbgD
+ 01O8DoZA02c1MUMbMHRPSb/qdok2pyWoCPa/BSaOIaNPePc8auPRbrS2XsVWSMft
+ CTXiXmrK2Xx1+fJuZLAp0CUng4De4cDH5c8nvlocYmXo+1x53S9DfD0KPryjBRI7
+ 9LnJq2ysHAUawiqFXlwBag6mXawD8YjzcYat
+ -----END CERTIFICATE-----
+ """) + "\n"
+
+ self.private_key = trim("""-----BEGIN RSA PRIVATE KEY-----
+ MIICXQIBAAKBgQCmcXbusrr8zQr8snIb0OVQibVfgv7zPjh/5xdcrKOejJzp3epA
+ AF4TITeFR9vzWIwkmkcRoY+IbQNhh7kefGUYD47bvVamJMtq5cGYVs0HngT+KTMa
+ NGH/G44KkFIOaz/b5d/JNKONrlqwxqXS+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQAB
+ AoGBAIcDv4A9h6UOBv2ZGyspNvsv2erSblGOhXJrWO4aNNemJJspIp4sLiPCbDE3
+ a1po17XRWBkbPz1hgL6axDXQnoeo++ebfrvRSed+Fys4+6SvuSrPOv6PmWTBT/Wa
+ GpO+tv48JUNxC/Dy8ROixBXOViuIBEFq3NfVH4HU3+RG20NhAkEA1L3RAhdfPkLI
+ 82luSOYE3Eq44lICb/yZi+JEihwSeZTJKdZHwYD8KVCjOtjGrOmyEyvThrcIACQz
+ JLEreVh33wJBAMhJm9pzJJNkIyBgiXA66FAwbhdDzSTPx0OBjoVWoj6u7jzGvIFT
+ Cn1aiTBYzzsiMCaCx+W3e6pK/DcvHSwKrgkCQHZMcxwBmSHLC2lnmD8LQWqqVnLr
+ fZV+VnfVw501DQT0uoP8NvygWBg1Uf9YKepfLXnBpidEQjup5ZKivnUEv+sCQA8N
+ 6VcMHI2vkyxV1T7ITrnoSf4ZrIu9yl56mHnRPzSy9VlAHt8hnMI7UeB+bGUndrMO
+ VXQgzHzKUhbbxbePvfECQQDTtkOuhJyKDfHCxLDcwNpi+T6OWTEfCw/cq9ZWDbA7
+ yCX81pQxfZkfMIS1YFIOGHovK0rMMTraCe+iDNYtVz/L
+ -----END RSA PRIVATE KEY-----
+ """) + "\n"
+
+ self.certificate = trim("""-----BEGIN CERTIFICATE-----
+ MIIB9zCCAWACCQDjWWTeC6BQvTANBgkqhkiG9w0BAQQFADBAMQswCQYDVQQGEwJB
+ VTETMBEGA1UECBMKU29tZS1TdGF0ZTEcMBoGA1UEChMTV2ViS2l0IExheW91dCBU
+ ZXN0czAeFw0wNzA3MTMxMjUxMzJaFw03MTA1MTMwNjIzMTZaMEAxCzAJBgNVBAYT
+ AkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRwwGgYDVQQKExNXZWJLaXQgTGF5b3V0
+ IFRlc3RzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmcXbusrr8zQr8snIb
+ 0OVQibVfgv7zPjh/5xdcrKOejJzp3epAAF4TITeFR9vzWIwkmkcRoY+IbQNhh7ke
+ fGUYD47bvVamJMtq5cGYVs0HngT+KTMaNGH/G44KkFIOaz/b5d/JNKONrlqwxqXS
+ +m6IY4l/E1Ff25ZjND5TaEvI1wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAAfbUbgD
+ 01O8DoZA02c1MUMbMHRPSb/qdok2pyWoCPa/BSaOIaNPePc8auPRbrS2XsVWSMft
+ CTXiXmrK2Xx1+fJuZLAp0CUng4De4cDH5c8nvlocYmXo+1x53S9DfD0KPryjBRI7
+ 9LnJq2ysHAUawiqFXlwBag6mXawD8YjzcYat
+ -----END CERTIFICATE-----
+ """) + "\n"
+
+
+# Formal docstring indentation handling from PEP
+# https://www.python.org/dev/peps/pep-0257/
+def trim(docstring):
+ if not docstring:
+ return ''
+ # Convert tabs to spaces (following the normal Python rules)
+ # and split into a list of lines:
+ lines = docstring.expandtabs().splitlines()
+ # Determine minimum indentation (first line doesn't count):
+ indent = sys.maxint
+ for line in lines[1:]:
+ stripped = line.lstrip()
+ if stripped:
+ indent = min(indent, len(line) - len(stripped))
+ # Remove indentation (first line is special):
+ trimmed = [lines[0].strip()]
+ if indent < sys.maxint:
+ for line in lines[1:]:
+ trimmed.append(line[indent:].rstrip())
+ # Strip off trailing and leading blank lines:
+ while trimmed and not trimmed[-1]:
+ trimmed.pop()
+ while trimmed and not trimmed[0]:
+ trimmed.pop(0)
+ # Return a single string:
+ return '\n'.join(trimmed)
Modified: trunk/Tools/Scripts/webkitpy/port/base.py (229540 => 229541)
--- trunk/Tools/Scripts/webkitpy/port/base.py 2018-03-12 17:53:39 UTC (rev 229540)
+++ trunk/Tools/Scripts/webkitpy/port/base.py 2018-03-12 18:05:36 UTC (rev 229541)
@@ -47,7 +47,7 @@
from webkitpy.common import read_checksum_from_png
from webkitpy.common.memoized import memoized
from webkitpy.common.prettypatch import PrettyPatch
-from webkitpy.common.system import path
+from webkitpy.common.system import path, pemfile
from webkitpy.common.system.executive import ScriptError
from webkitpy.common.version_name_map import PUBLIC_TABLE, INTERNAL_TABLE, VersionNameMap
from webkitpy.common.wavediff import WaveDiff
@@ -991,12 +991,6 @@
return True
return web_platform_test_server.is_wpt_server_running(self)
- def _extract_certificate_from_pem(self, pem_file, destination_certificate_file):
- return self._executive.run_command(['openssl', 'x509', '-outform', 'pem', '-in', pem_file, '-out', destination_certificate_file], return_exit_code=True) == 0
-
- def _extract_private_key_from_pem(self, pem_file, destination_private_key_file):
- return self._executive.run_command(['openssl', 'rsa', '-in', pem_file, '-out', destination_private_key_file], return_exit_code=True) == 0
-
def start_websocket_server(self):
"""Start a web server. Raise an error if it can't start or is already running.
@@ -1007,17 +1001,21 @@
server.start()
self._websocket_server = server
+ websocket_server_temporary_directory = self._filesystem.mkdtemp(prefix='webkitpy-websocket-server')
+ self._websocket_server_temporary_directory = websocket_server_temporary_directory
+
pem_file = self._filesystem.join(self.layout_tests_dir(), "http", "conf", "webkit-httpd.pem")
- websocket_server_temporary_directory = self._filesystem.mkdtemp(prefix='webkitpy-websocket-server')
+ pem = pemfile.load(self._filesystem, pem_file)
certificate_file = self._filesystem.join(str(websocket_server_temporary_directory), 'webkit-httpd.crt')
+ self._filesystem.write_text_file(certificate_file, pem.certificate)
private_key_file = self._filesystem.join(str(websocket_server_temporary_directory), 'webkit-httpd.key')
- self._websocket_server_temporary_directory = websocket_server_temporary_directory
- if self._extract_certificate_from_pem(pem_file, certificate_file) and self._extract_private_key_from_pem(pem_file, private_key_file):
- secure_server = self._websocket_secure_server = websocket_server.PyWebSocket(self, self.results_directory(),
- use_tls=True, port=websocket_server.PyWebSocket.DEFAULT_WSS_PORT, private_key=private_key_file, certificate=certificate_file)
- secure_server.start()
- self._websocket_secure_server = secure_server
+ self._filesystem.write_text_file(private_key_file, pem.private_key)
+ secure_server = self._websocket_secure_server = websocket_server.PyWebSocket(self, self.results_directory(),
+ use_tls=True, port=websocket_server.PyWebSocket.DEFAULT_WSS_PORT, private_key=private_key_file, certificate=certificate_file)
+ secure_server.start()
+ self._websocket_secure_server = secure_server
+
def start_web_platform_test_server(self, additional_dirs=None, number_of_servers=None):
assert not self._web_platform_test_server, 'Already running a Web Platform Test server.'