class TCellAgent::Instrumentation::Rails::Middleware::HeadersMiddleware

Public Class Methods

new(app) click to toggle source
# File lib/tcell_agent/rails/middleware/headers_middleware.rb, line 12
def initialize(app)
  @app = app
end

Public Instance Methods

_handle_appsensor_js_agent_and_dlp(request, response) click to toggle source
# File lib/tcell_agent/rails/middleware/headers_middleware.rb, line 80
def _handle_appsensor_js_agent_and_dlp(request, response)
  TCellAgent::Instrumentation.safe_block('Handling AppSensor, JS Agent, and DLP') do
    status_code, response_headers, response_body = response

    js_agent_handler, script_insert =
      TCellAgent::Instrumentation::Rails::JSAgent.get_handler_and_script_insert(request, response_headers)
    dlp_handler, tcell_context =
      TCellAgent::Instrumentation::Rails::DLPHandler.get_handler_and_context(request, response_headers)

    content_length = 0
    defer_appfw_due_to_streaming = false

    if TCellAgent::Utils::Rails.empty_content?(status_code, response_headers)
      content_length = 0

    elsif response_headers['Content-Length']
      content_length = response_headers['Content-Length'].to_i

      # when content length is present it can be inferred that the
      # response is not a streaming response, so js agent insertion
      # and dlp reports and redactions can be done up front
      response_body, content_length =
        TCellAgent::Instrumentation::Rails::JSAgent.insert_now(js_agent_handler,
                                                               script_insert,
                                                               response_body,
                                                               content_length)

      response_body, content_length =
        TCellAgent::Instrumentation::Rails::DLPHandler.report_and_redact_now(dlp_handler,
                                                                             tcell_context,
                                                                             response_body,
                                                                             content_length)

      response_headers['Content-Length'] = content_length.to_s

    elsif response_body.is_a?(Rack::BodyProxy)
      response_body = TCellAgent::Instrumentation::Rails::TCellBodyProxy.new(
        response_body,
        TCellAgent::Utils::Rails.processable_response?(response_headers),
        js_agent_handler,
        script_insert,
        dlp_handler,
        tcell_context
      )
      defer_appfw_due_to_streaming = true
    end

    appfirewall_policy = TCellAgent.policy(TCellAgent::PolicyTypes::APPSENSOR)
    if appfirewall_policy.enabled
      meta_data = TCellAgent::MetaData.for_appfirewall(
        request, content_length, status_code, response_headers
      )
      if defer_appfw_due_to_streaming
        response_body.meta_data = meta_data
      else
        appfirewall_policy.check_appfirewall_injections(meta_data)
      end
    end

    return [status_code, response_headers, response_body]
  end

  response
end
_handle_redirect(request, response) click to toggle source
# File lib/tcell_agent/rails/middleware/headers_middleware.rb, line 61
def _handle_redirect(request, response)
  TCellAgent::Instrumentation.safe_block('Handling Redirect Headers') do
    status, headers, active_response = response
    if headers.key?('Location')
      http_redirect_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HTTPREDIRECT)
      tcell_context = request.env[TCellAgent::Instrumentation::TCELL_ID]
      from_domain = URI.parse(tcell_context.uri).host
      new_location = http_redirect_policy.check_redirect(
        headers['Location'], from_domain, status, tcell_context
      )

      # Enforcement
      headers['Location'] = new_location if new_location
    end
    response = [status, headers, active_response]
  end
  response
end
_set_headers(request, response) click to toggle source
# File lib/tcell_agent/rails/middleware/headers_middleware.rb, line 36
def _set_headers(request, response)
  status, headers, active_response = response

  TCellAgent::Instrumentation.safe_block('Handling headers') do
    headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HEADERS)
    policy_headers = headers_policy.get_headers(
      headers['Content-Type'],
      request.env[TCellAgent::Instrumentation::TCELL_ID]
    )
    policy_headers.each do |header_info|
      header_name = header_info['name']
      header_value = header_info['value']
      existing_header_value = headers[header_name]
      headers[header_name] = if existing_header_value
                               "#{existing_header_value}, #{header_value}"
                             else
                               header_value
                             end
    end
    response = [status, headers, active_response]
  end

  response
end
call(env) click to toggle source
# File lib/tcell_agent/rails/middleware/headers_middleware.rb, line 16
def call(env)
  request = Rack::Request.new(env)

  response = @app.call(env)

  if TCellAgent.configuration.should_intercept_requests?
    TCellAgent::Instrumentation.safe_block('Handling Request') do
      tcell_response = response
      unless request.env[TCellAgent::Instrumentation::TCELL_ID].patches_blocking_triggered
        tcell_response = _handle_appsensor_js_agent_and_dlp(request, tcell_response)
      end
      tcell_response = _handle_redirect(request, tcell_response)
      tcell_response = _set_headers(request, tcell_response)
      response = tcell_response
    end
  end

  response
end