def _process(self, flow: HTTPFlow, phase: Phase): route, filters = match_route( proxy_mode=ctx.get_proxy_context().mode, phase=phase, flow=flow, ) if not route: return match_details = {'filters': [], 'route_id': route.id} matched_filters = match_details['filters'] for fltr in filters: if fltr.has_operations: pipeline = build_pipeline(fltr) pipeline.evaluate(flow, phase) operation_applied = True else: operation_applied = transform(flow, phase, fltr) matched_filters.append({ 'id': fltr.id, 'operation_applied': operation_applied, }) phase_obj = getattr(flow, phase.value.lower()) phase_obj.match_details = match_details
def request(self, flow: HTTPFlow): try: audit_logs.emit( audit_logs.records.VaultRequestAuditLogRecord( flow_id=flow.id, proxy_mode=ctx.get_proxy_context().mode, method=flow.request.method, uri=flow.request.url, )) flow.request_raw = flow.request.copy() self._process(flow, Phase.REQUEST) except (RedactFailed, RevealFailed) as exc: logger.error(exc) except Exception as exc: logger.exception(exc)
def reveal(alias: str) -> str: alias_entity = get_by_alias(alias) if not alias_entity: raise RevealFailed('Alias was not found!') flow_context = ctx.get_flow_context() audit_logs.emit( audit_logs.VaultRecordUsageLogRecord( alias_generator=alias_entity.alias_generator, flow_id=flow_context.flow.id, phase=flow_context.phase, proxy_mode=ctx.get_proxy_context().mode, route_id=ctx.get_route_context().route.id, action_type=audit_logs.ActionType.RETRIEVED, record_id=alias_entity.id, )) return alias_entity.value
def redact(value: str, alias_generator: str) -> str: flow_context = ctx.get_flow_context() make_log_record = partial( audit_logs.VaultRecordUsageLogRecord, alias_generator=alias_generator, flow_id=flow_context.flow.id, phase=flow_context.phase, proxy_mode=ctx.get_proxy_context().mode, route_id=ctx.get_route_context().route.id, ) alias_entity = get_by_value(value) if alias_entity: audit_logs.emit( make_log_record( action_type=audit_logs.ActionType.DE_DUPE, record_id=alias_entity.id, )) return alias_entity.public_alias alias_generator_type = generator_map.get(alias_generator) alias_id = str(uuid.uuid4()) if not alias_generator_type: raise RedactFailed( f'{alias_generator} can\'t be used as a alias generator. ' f'Possible values: {str(alias_generator.keys())}') public_alias = alias_generator_type.generate(alias_id) alias = Alias( id=alias_id, value=value, alias_generator=alias_generator, public_alias=public_alias, ) session = get_session() session.add(alias) session.commit() audit_logs.emit( make_log_record( action_type=audit_logs.ActionType.CREATED, record_id=alias.id, )) return public_alias
def response(self, flow: HTTPFlow): try: proxy_context = ctx.get_proxy_context() for sock, label in [ (flow.server_conn.wfile, audit_logs.TrafficLabel.TO_SERVER), (flow.server_conn.rfile, audit_logs.TrafficLabel.FROM_SERVER), ]: if sock and sock.is_logging(): # TODO: (SAT-98) trigger TO_SERVER-event at the right time. audit_logs.emit( audit_logs.VaultTrafficLogRecord( flow_id=flow.id, proxy_mode=proxy_context.mode, bytes=len(sock.get_log()), label=label, )) sock.stop_log() audit_logs.emit( audit_logs.UpstreamResponseLogRecord( flow_id=flow.id, proxy_mode=proxy_context.mode, upstream=flow.request.host, status_code=flow.response.status_code, )) flow.response_raw = flow.response.copy() content, match_details = self._process( flow=flow, phase=Phase.RESPONSE, content=flow.response.content, ) if match_details: flow.response.text = content flow.response.match_details = match_details except (RedactFailed, RevealFailed) as exc: logger.error(exc) except Exception as exc: logger.exception(exc)
def _process(self, flow: HTTPFlow, phase: Phase, content: bytes) -> Tuple[str, dict]: route, route_filters = match_route( proxy_mode=ctx.get_proxy_context().mode, phase=phase, flow=flow, ) if not route_filters: return content, None with ctx.use_context(ctx.FlowContext( flow=flow, phase=phase)), ctx.use_context(ctx.RouteContext(route=route)): # TODO: Encapsulate flow transformation somewere else content, ops_applications = transform_body(route_filters, content) matched_filters = [{ 'id': rule.id, 'operation_applied': op_applied } for rule, op_applied in zip(route_filters, ops_applications)] return content, {'route_id': route.id, 'filters': matched_filters}
def request(self, flow: HTTPFlow): try: audit_logs.emit( audit_logs.VaultRequestAuditLogRecord( flow_id=flow.id, proxy_mode=ctx.get_proxy_context().mode, method=flow.request.method, uri=flow.request.url, )) flow.request_raw = flow.request.copy() content, match_details = self._process( flow=flow, phase=Phase.REQUEST, content=flow.request.content, ) if match_details: flow.request.text = content flow.request.match_details = match_details except (RedactFailed, RevealFailed) as exc: logger.error(exc) except Exception as exc: logger.exception(exc)
def test_use_context(context): with ctx.use_context(context): assert ctx.get_proxy_context() == context with pytest.raises(ctx.ContextError): ctx.del_context(ctx.ProxyContext)
def test_get_unset_context(): with pytest.raises(ctx.ContextError): ctx.get_proxy_context()
def test_get_set_context_ok(context): ctx.set_context(context) try: assert ctx.get_proxy_context() == context finally: ctx.del_context(ctx.ProxyContext)
def test_get_unset_context(): assert ctx.get_proxy_context() is None