def __call__(self, environ, start_response): self.environ = environ self.start_response = start_response try: self.full_uri = environ['SCRIPT_URI'] self.path = environ['SCRIPT_URL'][len(environ['SCRIPT_NAME']):] self.host = environ['wsgi.url_scheme'] + "://" + environ[ 'SERVER_NAME'] except: self.full_uri = environ['REQUEST_URI'] self.path = environ['PATH_INFO'] self.host = environ['HTTP_HOST'] if environ['QUERY_STRING']: #self.query = urlparse.parse_qs(environ['QUERY_STRING']) self.query = parse_qs(environ['QUERY_STRING']) else: self.query = {} try: self.body = environ['wsgi.input'].read() except: self.body = '' h = {} for (k, v) in environ.items(): if k.startswith('HTTP_'): name = k[5:].lower().replace('_', '-') h[name] = v self.in_headers = h self.status = 200 self.out_headers = headers.Headers([]) try: data = self.handle() except: sio = StringIO.StringIO() cgitb.Hook(file=sio).handle() sio.seek(0) data = sio.read() self.out_headers['Content-type'] = 'text/html' self.status = 500 self.out_headers['Content-length'] = str(len(data)) status = "%s %s" % (self.status, self.codes[self.status]) start_response(status, self.out_headers.items()) if type(data) == str: return [data] elif type(data) == unicode: return [data.encode('utf-8')] else: # see if response is iterable try: iter(data) return data except TypeError: return [data]
def __init__(self, http_method=None, service_path=None, headers=None, **kwargs): """Constructor. Args: Same as RequestState, including: http_method: Assigned to property. service_path: Assigned to property. headers: HTTP request headers. If instance of Headers, assigned to property without copying. If dict, will convert to name value pairs for use with Headers constructor. Otherwise, passed as parameters to Headers constructor. """ super(HttpRequestState, self).__init__(**kwargs) self.__http_method = http_method self.__service_path = service_path # Initialize headers. if isinstance(headers, dict): header_list = [] for key, value in sorted(headers.items()): if not isinstance(value, list): value = [value] for item in value: header_list.append((key, item)) headers = header_list self.__headers = wsgi_headers.Headers(headers or [])
def __init__(self, uri): """Set up various useful defaults.""" self._headers = [] self.headers = headers.Headers(self._headers) guess = mimetypes.guess_type(uri)[0] self.headers['Content-Type'] = guess or 'text/html' self.status = '200 OK' self.body = ""
def CspStartResponse(status, headers, exc_info=None): """Add the CSP header to the response. Signature determined by WSGI.""" # If the headers are given to us as a list or a dict, convert that to a # Headers object which can correctly support duplicate headers. if isinstance(headers, list): headers = wsgi_headers.Headers(headers) elif isinstance(headers, dict): headers = wsgi_headers.Headers(list(headers.items())) # Set CSP header if CSP is enabled. if csp_enabled: headers.add_header(csp_header_key, csp_directives) # Set Trusted Types CSP header if Trusted Types are enabled. if tt_enabled: headers.add_header(tt_header_key, tt_directives) # Pass the headers to the next middleware as a List[Tuple[str, str]] since # gunicorn needs them in that format. return start_response(status, headers.items(), exc_info)
def __init__(self, connection): self._connection = connection self.headers = headers.Headers([('Transfer-Encoding', 'chunked')]) self.out = OutFile(self._connection)
class CspTest(parameterized.TestCase, test_lib.GRRBaseTest): """Tests for Csp.""" def testGetCspHeaderKey(self): enforced_result = csp.GetCspHeaderKey(False) report_only_result = csp.GetCspHeaderKey(True) self.assertEqual(csp.HEADER_KEY_ENFORCE, enforced_result) self.assertEqual(csp.HEADER_KEY_REPORT_ONLY, report_only_result) def testBuildPolicy(self): expected_directives = [ "upgrade-insecure-requests", "default-src 'self'", "base-uri 'none'", "object-src 'none'", "img-src 'self' https: data:" ] result = csp.BuildPolicy(test_policy) result_directives = [x.strip() for x in result.split(";")] self.assertCountEqual(expected_directives, result_directives) @parameterized.named_parameters( dict( testcase_name="Disable CSP", csp_enabled=False, csp_report_only=False, tt_enabled=False, tt_report_only=False, expected_headers=[]), dict( testcase_name="Enable enforced Trusted Types, with an existing CSP header", csp_enabled=False, csp_report_only=True, tt_enabled=True, tt_report_only=False, existing_headers=[(csp.HEADER_KEY_ENFORCE, "existing policy")], expected_headers=[(csp.HEADER_KEY_ENFORCE, "existing policy"), (csp.HEADER_KEY_ENFORCE, "require-trusted-types-for 'script'")]), dict( testcase_name="Enable enforced CSP, with custom policy", csp_enabled=True, csp_policy='{"frame-ancestors": ["\'self\'"], "foo": ["bar"]}', csp_report_only=False, tt_enabled=False, expected_headers=[(csp.HEADER_KEY_ENFORCE, "frame-ancestors 'self'; foo bar")]), dict( testcase_name="Enable enforced CSP & trusted types, with custom policy", csp_enabled=True, csp_policy='{"frame-ancestors": ["\'self\'"], "foo": ["bar"]}', csp_report_only=False, tt_enabled=True, tt_report_only=False, expected_headers=[ (csp.HEADER_KEY_ENFORCE, "frame-ancestors 'self'; foo bar"), (csp.HEADER_KEY_ENFORCE, "require-trusted-types-for 'script'") ]), dict( testcase_name="Enable report-only CSP, no trusted types, with report URL", csp_enabled=True, csp_report_only=True, tt_enabled=False, report_uri="test", expected_headers=[(csp.HEADER_KEY_REPORT_ONLY, "report-uri test")]), dict( testcase_name="Enable report-only trusted types", csp_enabled=False, csp_report_only=False, tt_enabled=True, tt_report_only=True, expected_headers=[(csp.HEADER_KEY_REPORT_ONLY, "require-trusted-types-for 'script'")]), dict( testcase_name="Enable report-only trusted types with report URL", csp_enabled=False, csp_report_only=False, tt_enabled=True, tt_report_only=True, report_uri="test", expected_headers=[ (csp.HEADER_KEY_REPORT_ONLY, "require-trusted-types-for 'script'; report-uri test") ]), dict( testcase_name="Set headers for URLs in the include list", csp_enabled=True, csp_report_only=False, csp_policy='{"frame-ancestors": ["\'self\'"], "foo": ["bar"]}', tt_enabled=True, tt_report_only=True, url_path="/v2/page.html", include_prefixes=["/v2"], expected_headers=[ (csp.HEADER_KEY_ENFORCE, "frame-ancestors 'self'; foo bar"), (csp.HEADER_KEY_REPORT_ONLY, "require-trusted-types-for 'script'") ]), dict( testcase_name="Don't set headers for URLs not in the include list", csp_enabled=True, tt_enabled=True, url_path="/v1/page.html", include_prefixes=["/v2"], expected_headers=[]), dict( testcase_name="Don't set headers for URLs in the exclude list", csp_enabled=True, tt_enabled=True, url_path="/v1/page.html", exclude_prefixes=["/v1"], expected_headers=[]), dict( testcase_name="Handle specifying both an include and exclude list", csp_enabled=True, tt_enabled=True, url_path="/v2/not-this-one.html", include_prefixes=["/v2"], exclude_prefixes=["/v2/not-this-one.html"], expected_headers=[]), dict( testcase_name="Handle duplicate headers as a list", csp_enabled=False, tt_enabled=True, existing_headers=[("Set-Cookie", "foo=bar"), ("Set-Cookie", "bin=baz")], expected_headers=[ ("Set-Cookie", "foo=bar"), ("Set-Cookie", "bin=baz"), (csp.HEADER_KEY_REPORT_ONLY, "require-trusted-types-for 'script'") ]), dict( testcase_name="Handle duplicate headers as wsgi headers", csp_enabled=False, tt_enabled=True, existing_headers=wsgi.Headers([("Set-Cookie", "foo=bar"), ("Set-Cookie", "bin=baz")]), expected_headers=[ ("Set-Cookie", "foo=bar"), ("Set-Cookie", "bin=baz"), (csp.HEADER_KEY_REPORT_ONLY, "require-trusted-types-for 'script'") ]), dict( testcase_name="Handle headers as a dict", csp_enabled=False, tt_enabled=True, existing_headers={"Set-Cookie": "foo=bar"}, expected_headers=[("Set-Cookie", "foo=bar"), (csp.HEADER_KEY_REPORT_ONLY, "require-trusted-types-for 'script'")]), dict( testcase_name="Raise an exception if multiple report URIs are given", csp_enabled=True, tt_enabled=False, csp_policy='{"report-uri": ["test"], "foo": ["bar"]}', report_uri="test", expected_exception=RuntimeError), ) def testCspMiddleware(self, csp_enabled=False, csp_policy="{}", csp_report_only=True, tt_enabled=False, tt_report_only=True, report_uri="", include_prefixes=(), exclude_prefixes=(), url_path="", existing_headers=(), expected_headers=(), expected_exception=None): """Test if CSP headers are correctly set.""" expected_output = "Response successfully processed" environ_stub = {"PATH_INFO": url_path} def ApplicationStub(unused_environ, start_response): return start_response(200, existing_headers or []) def StartResponseMock(unused_status, headers, unused_exc_info=None): """This mock is called at the end of CspStartResponse.""" self.assertEqual(headers, expected_headers) return expected_output with test_lib.ConfigOverrider({ "AdminUI.csp_enabled": csp_enabled, "AdminUI.csp_policy": csp_policy, "AdminUI.csp_report_only": csp_report_only, "AdminUI.trusted_types_enabled": tt_enabled, "AdminUI.trusted_types_report_only": tt_report_only, "AdminUI.csp_report_uri": report_uri, "AdminUI.csp_include_url_prefixes": include_prefixes, "AdminUI.csp_exclude_url_prefixes": exclude_prefixes }): if expected_exception: with self.assertRaises(expected_exception): csp.CspMiddleware(ApplicationStub) else: test_app = csp.CspMiddleware(ApplicationStub) output = test_app(environ_stub, StartResponseMock) self.assertEqual(expected_output, output)