class TCellAgent::Rust::NativeAgent

Attributes

agent_ptr[R]

Public Class Methods

create_agent(config) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 35
def self.create_agent(config)
  return nil unless TCellAgent::Rust::NativeLibrary.common_lib_available?

  agent_config = TCellAgent::Rust::AgentConfig.new(config)
  config_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(agent_config)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # config_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.create_agent(
    config_pointer, config_pointer.size - 1, buf, buf.size
  )

  response = JSON.parse(buf.get_string(0, result_size))
  if response['error']
    logger = TCellAgent::ModuleLogger.new(TCellAgent::RubyLogger.new, name)
    logger.error("Error creating native agent: #{response['error']}")
    return nil
  end

  return unless response['config'] && response['agent_enabled']

  TCellAgent.configuration.populate_configuration(response['config'])
  NativeAgent.new(response['agent_ptr'])
end
free_agent(agent_ptr) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 26
def self.free_agent(agent_ptr)
  if TCellAgent::Rust::NativeLibrary.common_lib_available? &&
     agent_ptr
    TCellAgent::Rust::NativeLibrary.free_agent(
      FFI::Pointer.new(agent_ptr)
    )
  end
end
new(agent_ptr) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 64
def initialize(agent_ptr)
  @agent_ptr = agent_ptr
end
test_agent(config) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 12
def self.test_agent(config)
  agent_config = TCellAgent::Rust::AgentConfig.new(config)

  config_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(agent_config)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # config_pointer.size - 1: strips null terminator
  TCellAgent::Rust::NativeLibrary.test_agent(
    config_pointer, config_pointer.size - 1, buf, buf.size
  )
end

Public Instance Methods

apply_appfirewall(appsensor_meta) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 68
def apply_appfirewall(appsensor_meta)
  return {} unless appsensor_meta

  post_params = Models.convert_params(appsensor_meta.flattened_post_dict)
  query_params = Models.convert_params(appsensor_meta.flattened_get_dict)
  header_params = Models.convert_params(appsensor_meta.flattened_headers_dict)
  cookie_params = Models.convert_params(appsensor_meta.flattened_cookie_dict)
  path_params = Models.convert_params(appsensor_meta.flattened_path_parameters)

  request_response_json = {
    :method => appsensor_meta.method,
    :status_code => appsensor_meta.response_code.to_i,
    :route_id => appsensor_meta.route_id,
    :path => appsensor_meta.path,
    :query_params => query_params,
    :post_params => post_params,
    :headers => header_params,
    :cookies => cookie_params,
    :path_params => path_params,
    :reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
    :remote_address => appsensor_meta.remote_address,
    :full_uri => appsensor_meta.location,
    :session_id => appsensor_meta.session_id,
    :user_id => appsensor_meta.user_id,
    :user_agent => appsensor_meta.user_agent,
    :request_bytes_length => appsensor_meta.request_content_bytes_len,
    :response_bytes_length => appsensor_meta.response_content_bytes_len,
    :content_type => appsensor_meta.content_type,
    :request_body => appsensor_meta.raw_request_body
  }
  request_response_json[:sql_exceptions] = appsensor_meta.sql_exceptions if appsensor_meta.sql_exceptions
  request_response_json[:database_result_sizes] = appsensor_meta.database_result_sizes if appsensor_meta.database_result_sizes

  if TCellAgent::Utils::Strings.present?(appsensor_meta.csrf_exception_name)
    request_response_json[:csrf_exception] = {
      :exception_name => appsensor_meta.csrf_exception_name
    }
  end

  request_response_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(request_response_json)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # request_response_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.appfirewall_apply(
    FFI::Pointer.new(@agent_ptr),
    request_response_pointer,
    request_response_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('apply_appfirewall', buf, result_size)
  log_response_errors(response.errors)
  response.response
end
apply_cmdi(command, tcell_context) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 200
def apply_cmdi(command, tcell_context)
  return unless TCellAgent::Utils::Strings.present?(command)

  command_info = {
    :command => command,
    :method => tcell_context.request_method,
    :path => tcell_context.path,
    :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
    :remote_address => tcell_context.remote_address,
    :route_id => tcell_context.route_id,
    :session_id => tcell_context.session_id,
    :user_id => tcell_context.user_id,
    :full_uri => tcell_context.uri
  }

  command_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(command_info)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # command_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.cmdi_apply(
    FFI::Pointer.new(@agent_ptr),
    command_pointer,
    command_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('apply_cmdi', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
apply_patches(appsensor_meta) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 126
def apply_patches(appsensor_meta)
  return {} unless appsensor_meta

  post_params = Models.convert_params(appsensor_meta.flattened_post_dict)
  query_params = Models.convert_params(appsensor_meta.flattened_get_dict)
  header_params = Models.convert_params(appsensor_meta.flattened_headers_dict)
  cookie_params = Models.convert_params(appsensor_meta.flattened_cookie_dict)

  patches_request_json = {
    :method => appsensor_meta.method,
    :path => appsensor_meta.path,
    :remote_address => appsensor_meta.remote_address,
    :reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
    :request_bytes_length => appsensor_meta.request_content_bytes_len,
    :query_params => query_params,
    :post_params => post_params,
    :headers => header_params,
    :cookies => cookie_params,
    :content_type => appsensor_meta.content_type,
    :full_uri => appsensor_meta.location,
    :request_body => appsensor_meta.raw_request_body
  }

  patches_request_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(patches_request_json)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # patches_request_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.patches_apply(
    FFI::Pointer.new(@agent_ptr),
    patches_request_pointer,
    patches_request_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('apply_patches', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
apply_suspicious_quick_check(appsensor_meta) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 169
def apply_suspicious_quick_check(appsensor_meta)
  return {} unless appsensor_meta

  sus_quick_check_request_json = {
    :reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
    :method => appsensor_meta.method,
    :path => appsensor_meta.path,
    :full_uri => appsensor_meta.location,
    :request_bytes_length => appsensor_meta.request_content_bytes_len
  }

  if appsensor_meta.reverse_proxy_header_value.nil?
    sus_quick_check_request_json.merge(
      {
        :client_ip_override => appsensor_meta.remote_address
      }
    )
  end

  sus_quick_check_request_ptr = FFI::MemoryPointer.from_string(
    JSON.dump(sus_quick_check_request_json)
  )

  # sus_quick_check_request_ptr.size - 1: strips null terminator
  TCellAgent::Rust::NativeLibrary.suspicious_quick_check_apply(
    FFI::Pointer.new(@agent_ptr),
    sus_quick_check_request_ptr,
    sus_quick_check_request_ptr.size - 1
  )
end
check_http_redirect(location_header, from_domain, status_code, tcell_context) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 265
def check_http_redirect(location_header,
                        from_domain,
                        status_code,
                        tcell_context)
  return {} unless tcell_context

  http_redirect_request = {
    :location_header => location_header,
    :local_server => from_domain,
    :status_code => status_code,
    :method => tcell_context.request_method,
    :path => tcell_context.path,
    :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
    :remote_addr => tcell_context.remote_address,
    :full_uri => tcell_context.uri,
    :route_id => tcell_context.route_id,
    :session_id => tcell_context.session_id,
    :user_id => tcell_context.user_id
  }
  http_redirect_request_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(http_redirect_request)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # http_redirect_request_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.check_http_redirect(
    FFI::Pointer.new(@agent_ptr),
    http_redirect_request_pointer,
    http_redirect_request_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('check_http_redirect', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
file_access_apply(file_path, mode, tcell_context) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 373
def file_access_apply(file_path,
                      mode,
                      tcell_context)

  file_access_info = {
    :dir_classification => 'Unknown',
    :file_path => file_path,
    :mode => mode
  }

  if tcell_context
    file_access_info = file_access_info.merge(
      {
        :full_uri => tcell_context.uri,
        :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
        :remote_address => tcell_context.remote_address,
        :route_id => tcell_context.route_id,
        :session_id => tcell_context.session_id,
        :user_id => tcell_context.user_id,
        :method => tcell_context.request_method,
        :request_path => tcell_context.path
      }
    )
  end

  file_access_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(file_access_info)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # login_info_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.file_access_apply(
    FFI::Pointer.new(@agent_ptr),
    file_access_pointer,
    file_access_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('file_access_apply', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
get_headers(content_type, tcell_context) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 235
def get_headers(content_type, tcell_context)
  return unless tcell_context

  headers_request = {
    :content_type => content_type,
    :method => tcell_context.request_method,
    :path => tcell_context.path,
    :route_id => tcell_context.route_id.to_s,
    :session_id => tcell_context.session_id.to_s
  }
  headers_request_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(headers_request)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 16)
  # headers_request_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.get_headers(
    FFI::Pointer.new(@agent_ptr),
    headers_request_pointer,
    headers_request_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('get_headers', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
get_js_agent_script_tag(tcell_context) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 304
def get_js_agent_script_tag(tcell_context)
  return {} unless tcell_context

  jsagent_request = {
    :method => tcell_context.request_method,
    :path => tcell_context.path
  }
  jsagent_request_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(jsagent_request)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # jsagent_request_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.get_js_agent_script_tag(
    FFI::Pointer.new(@agent_ptr),
    jsagent_request_pointer,
    jsagent_request_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('get_js_agent_script_tag', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
log_message(level, message, thread) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 488
def log_message(level, message, thread)
  return unless level && message

  message_json = {
    :level => level,
    :message => message,
    :thread => thread
  }
  message_json_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(message_json)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # message_json_pointer.size - 1: strips null terminator
  TCellAgent::Rust::NativeLibrary.log_message(
    FFI::Pointer.new(@agent_ptr),
    message_json_pointer,
    message_json_pointer.size - 1,
    buf,
    buf.size
  )
end
log_response_errors(errors) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 511
def log_response_errors(errors)
  errors.each do |error|
    log_message('error', error, self.class.name)
  end
end
login_fraud_apply(success, user_id, password, headers, user_valid, tcell_context) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 331
def login_fraud_apply(success,
                      user_id,
                      password,
                      headers,
                      user_valid,
                      tcell_context)
  event_name =  success ? :Success : :Failure
  header_keys = TCellAgent::Utils::Headers.clean_keys(headers)
  login_info = {
    :event_name => event_name,
    :user_id => user_id,
    :user_agent => tcell_context.user_agent,
    :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
    :remote_address => tcell_context.remote_address,
    :header_keys => header_keys,
    :password => password,
    :session_id => tcell_context.session_id,
    :full_uri => tcell_context.uri,
    :referrer => tcell_context.referrer,
    :user_valid => user_valid
  }

  login_info_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(login_info)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # login_info_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.login_fraud_apply(
    FFI::Pointer.new(@agent_ptr),
    login_info_pointer,
    login_info_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('login_fraud_apply', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
poll_new_policies() click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 418
def poll_new_policies
  buf = FFI::MemoryPointer.new(:uint8, 1024 * 32)
  result_size = TCellAgent::Rust::NativeLibrary.poll_new_policies(
    FFI::Pointer.new(@agent_ptr),
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('poll_new_policies', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
report_metrics(request_time, tcell_context) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 456
def report_metrics(request_time, tcell_context)
  return {} unless request_time

  message = {
    :elapsed_time => request_time,
    :route_id => tcell_context && tcell_context.route_id,
    :session_id => tcell_context && tcell_context.session_id,
    :user_id => tcell_context && tcell_context.user_id,
    :user_agent => tcell_context && tcell_context.user_agent,
    :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
    :remote_address => tcell_context && tcell_context.remote_address
  }
  message_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(message)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # message_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.report_metrics(
    FFI::Pointer.new(@agent_ptr),
    message_pointer,
    message_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('report_metrics', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
send_sanitized_events(events) click to toggle source
# File lib/tcell_agent/rust/native_agent.rb, line 432
def send_sanitized_events(events)
  return {} unless events

  events = { :events => events }
  events_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(events)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # events_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.send_sanitized_events(
    FFI::Pointer.new(@agent_ptr),
    events_pointer,
    events_pointer.size - 1,
    buf,
    buf.size
  )

  response = NativeAgentResponse.new('send_sanitized_events', buf, result_size)
  log_response_errors(response.errors)

  response.response
end
update_policies(policies) click to toggle source

NOTE: for tests

# File lib/tcell_agent/rust/native_agent.rb, line 518
def update_policies(policies)
  return {} unless TCellAgent::Utils::Strings.present?(policies)

  policies_pointer = FFI::MemoryPointer.from_string(
    JSON.dump(policies)
  )

  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
  # policies_pointer.size - 1: strips null terminator
  result_size = TCellAgent::Rust::NativeLibrary.update_policies(
    FFI::Pointer.new(agent_ptr),
    policies_pointer,
    policies_pointer.size - 1,
    buf,
    buf.size
  )

  NativeAgentResponse.new(
    'update_policies', buf, result_size
  ).response
end