Homeserver Whitlisting
parent
088176e5b2
commit
dde461814d
|
@ -18,6 +18,7 @@ import logging
|
|||
from jaeger_client import Config as JaegerConfig
|
||||
|
||||
from synapse.util.scopecontextmanager import LogContextScopeManager
|
||||
from synapse.util.tracerutils import TracerUtil
|
||||
|
||||
from ._base import Config, ConfigError
|
||||
|
||||
|
@ -37,7 +38,7 @@ class TracerConfig(Config):
|
|||
# If no whitelists are given
|
||||
self.tracer_config.setdefault("homeserver_whitelist", [])
|
||||
|
||||
if isinstance(self.tracer_config.get("homeserver_whitelist"), list):
|
||||
if not isinstance(self.tracer_config.get("homeserver_whitelist"), list):
|
||||
raise ConfigError("Tracer homesererver_whitelist config is malformed")
|
||||
|
||||
def generate_config_section(cls, **kwargs):
|
||||
|
@ -55,7 +56,7 @@ class TracerConfig(Config):
|
|||
|
||||
|
||||
def init_tracing(config):
|
||||
"""Initialise the JaegerClient tracer
|
||||
"""Set the whitelists and initialise the JaegerClient tracer
|
||||
|
||||
Args:
|
||||
config (Config)
|
||||
|
@ -64,6 +65,9 @@ def init_tracing(config):
|
|||
"""
|
||||
|
||||
if config.tracer_config.get("tracer_enabled", False):
|
||||
TracerUtil.set_homeserver_whitelist(
|
||||
config.tracer_config["homeserver_whitelist"]
|
||||
)
|
||||
jaeger_config = JaegerConfig(
|
||||
config={"sampler": {"type": "const", "param": 1}, "logging": True},
|
||||
service_name=config.server_name,
|
||||
|
|
|
@ -23,8 +23,6 @@ from six import PY3, raise_from, string_types
|
|||
from six.moves import urllib
|
||||
|
||||
import attr
|
||||
import opentracing
|
||||
from opentracing import tags
|
||||
import treq
|
||||
from canonicaljson import encode_canonical_json
|
||||
from opentracing.propagation import Format
|
||||
|
@ -39,6 +37,10 @@ from twisted.internet.task import _EPSILON, Cooperator
|
|||
from twisted.web._newclient import ResponseDone
|
||||
from twisted.web.http_headers import Headers
|
||||
|
||||
import opentracing
|
||||
from opentracing import tags
|
||||
from synapse.util.tracerutils import TracerUtil
|
||||
|
||||
import synapse.metrics
|
||||
import synapse.util.retryutils
|
||||
from synapse.api.errors import (
|
||||
|
@ -356,8 +358,9 @@ class MatrixFederationHttpClient(object):
|
|||
|
||||
# Inject the span into the headers
|
||||
headers_dict = {}
|
||||
opentracing.tracer.inject(scope.span, Format.HTTP_HEADERS, headers_dict)
|
||||
headers_dict = {k.encode(): [v.encode()] for k, v in headers_dict.items()}
|
||||
TracerUtil.inject_span_context_byte_dict(
|
||||
headers_dict, scope.span, request.destination
|
||||
)
|
||||
|
||||
headers_dict[b"User-Agent"] = [self.version_string_bytes]
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ from twisted.web.server import Request, Site
|
|||
from synapse.http import redact_uri
|
||||
from synapse.http.request_metrics import RequestMetrics, requests_counter
|
||||
from synapse.util.logcontext import LoggingContext, PreserveLoggingContext
|
||||
from synapse.util.tracerutils import extract_span_context
|
||||
from synapse.util.tracerutils import TracerUtil
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -239,7 +239,7 @@ class SynapseRequest(Request):
|
|||
)
|
||||
|
||||
# Start a span
|
||||
span_context = extract_span_context(self.requestHeaders)
|
||||
span_context = TracerUtil.extract_span_context(self.requestHeaders)
|
||||
opentracing.tracer.start_active_span(
|
||||
"incoming-federation-request",
|
||||
tags={
|
||||
|
|
|
@ -86,9 +86,6 @@ class LogContextScopeManager(ScopeManager):
|
|||
ctx.scope = scope
|
||||
return scope
|
||||
|
||||
def request_from_whitelisted_homeserver(self, request):
|
||||
pass
|
||||
|
||||
|
||||
class _LogContextScope(Scope):
|
||||
"""
|
||||
|
|
|
@ -13,51 +13,110 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.import opentracing
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
import opentracing
|
||||
from opentracing.propagation import Format
|
||||
|
||||
import re
|
||||
|
||||
def extract_span_context(headers):
|
||||
"""
|
||||
Extracts a span context from Twisted Headers.
|
||||
args:
|
||||
headers (twisted.web.http_headers.Headers)
|
||||
returns:
|
||||
span_context (opentracing.span.SpanContext)
|
||||
"""
|
||||
# Twisted encodes the values as lists whereas opentracing doesn't.
|
||||
# So, we take the first item in the list.
|
||||
# Also, twisted uses byte arrays while opentracing expects strings.
|
||||
header_dict = {k.decode(): v[0].decode() for k, v in headers.getAllRawHeaders()}
|
||||
return opentracing.tracer.extract(Format.HTTP_HEADERS, header_dict)
|
||||
# block everything by default
|
||||
|
||||
|
||||
def inject_span_context(headers, span):
|
||||
"""
|
||||
Injects a span context into twisted headers inplace
|
||||
args:
|
||||
headers (twisted.web.http_headers.Headers)
|
||||
span (opentracing.Span)
|
||||
class TracerUtil:
|
||||
_homeserver_whitelist = None
|
||||
|
||||
note:
|
||||
The headers set by the tracer are custom to the tracer implementation which
|
||||
should be unique enough that they don't interfere with any headers set by
|
||||
synapse or twisted. If we're still using jaeger these headers would be those
|
||||
here:
|
||||
https://github.com/jaegertracing/jaeger-client-python/blob/master/jaeger_client/constants.py
|
||||
"""
|
||||
carrier = {}
|
||||
carrier = opentracing.tracer.inject(span, Format.HTTP_HEADERS, {})
|
||||
@staticmethod
|
||||
def set_homeserver_whitelist(homeserver_whitelist):
|
||||
"""Sets the whitelist
|
||||
|
||||
for key, value in carrier:
|
||||
headers.addRawHeaders(key, value)
|
||||
Args:
|
||||
homeserver_whitelist (iterable of strings): regex of whitelisted homeservers
|
||||
"""
|
||||
if homeserver_whitelist:
|
||||
# Makes a single regex which accepts all passed in regexes in the list
|
||||
TracerUtil._homeserver_whitelist = re.compile(
|
||||
"({})".format(")|(".join(homeserver_whitelist))
|
||||
)
|
||||
logger.info("Set whitelist to {}".format(TracerUtil._homeserver_whitelist))
|
||||
|
||||
@staticmethod
|
||||
def whitelisted_homeserver(destination):
|
||||
if TracerUtil._homeserver_whitelist:
|
||||
return TracerUtil._homeserver_whitelist.match(destination)
|
||||
return False
|
||||
|
||||
# TODO: Implement whitelisting
|
||||
def request_from_whitelisted_homeserver(request):
|
||||
pass
|
||||
@staticmethod
|
||||
def extract_span_context(headers):
|
||||
"""
|
||||
Extracts a span context from Twisted Headers.
|
||||
args:
|
||||
headers (twisted.web.http_headers.Headers)
|
||||
returns:
|
||||
span_context (opentracing.span.SpanContext)
|
||||
"""
|
||||
# Twisted encodes the values as lists whereas opentracing doesn't.
|
||||
# So, we take the first item in the list.
|
||||
# Also, twisted uses byte arrays while opentracing expects strings.
|
||||
header_dict = {k.decode(): v[0].decode() for k, v in headers.getAllRawHeaders()}
|
||||
return opentracing.tracer.extract(Format.HTTP_HEADERS, header_dict)
|
||||
|
||||
@staticmethod
|
||||
def inject_span_context(headers, span, destination):
|
||||
"""
|
||||
Injects a span context into twisted headers inplace
|
||||
|
||||
# TODO: Implement whitelisting
|
||||
def user_whitelisted(request):
|
||||
pass
|
||||
Args:
|
||||
headers (twisted.web.http_headers.Headers)
|
||||
span (opentracing.Span)
|
||||
|
||||
Returns:
|
||||
Inplace modification of headers
|
||||
|
||||
Note:
|
||||
The headers set by the tracer are custom to the tracer implementation which
|
||||
should be unique enough that they don't interfere with any headers set by
|
||||
synapse or twisted. If we're still using jaeger these headers would be those
|
||||
here:
|
||||
https://github.com/jaegertracing/jaeger-client-python/blob/master/jaeger_client/constants.py
|
||||
"""
|
||||
|
||||
if not TracerUtil.whitelisted_homeserver(destination):
|
||||
return
|
||||
carrier = {}
|
||||
opentracing.tracer.inject(span, Format.HTTP_HEADERS, carrier)
|
||||
|
||||
for key, value in carrier.items():
|
||||
headers.addRawHeaders(key, value)
|
||||
|
||||
@staticmethod
|
||||
def inject_span_context_byte_dict(headers, span, destination):
|
||||
"""
|
||||
Injects a span context into a dict where the headers are encoded as byte
|
||||
strings
|
||||
|
||||
Args:
|
||||
headers (dict)
|
||||
span (opentracing.Span)
|
||||
|
||||
Returns:
|
||||
Inplace modification of headers
|
||||
|
||||
Note:
|
||||
The headers set by the tracer are custom to the tracer implementation which
|
||||
should be unique enough that they don't interfere with any headers set by
|
||||
synapse or twisted. If we're still using jaeger these headers would be those
|
||||
here:
|
||||
https://github.com/jaegertracing/jaeger-client-python/blob/master/jaeger_client/constants.py
|
||||
"""
|
||||
if not TracerUtil.whitelisted_homeserver(destination):
|
||||
logger.info("{}".format(TracerUtil._homeserver_whitelist))
|
||||
return
|
||||
|
||||
carrier = {}
|
||||
opentracing.tracer.inject(span, Format.HTTP_HEADERS, carrier)
|
||||
|
||||
for key, value in carrier.items():
|
||||
headers[key.encode()] = [value.encode()]
|
||||
|
|
Loading…
Reference in New Issue