229 lines
7.3 KiB
Ruby
229 lines
7.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "test_helper"
|
|
|
|
class Api::EventsControllerTest < ActionDispatch::IntegrationTest
|
|
def setup
|
|
@dsn = Dsn.create!(name: "Test DSN", key: "test-api-key-1234567890abcdef")
|
|
@disabled_dsn = Dsn.create!(name: "Disabled DSN", key: "disabled-key-1234567890abcdef", enabled: false)
|
|
|
|
@sample_event_data = {
|
|
"timestamp" => Time.current.iso8601,
|
|
"method" => "GET",
|
|
"path" => "/api/test",
|
|
"status" => 200,
|
|
"ip" => "192.168.1.100",
|
|
"user_agent" => "TestAgent/1.0"
|
|
}
|
|
end
|
|
|
|
test "should create event with valid DSN via query parameter" do
|
|
post api_events_path,
|
|
params: @sample_event_data.merge(baffle_key: @dsn.key),
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
assert_not_nil json_response["rule_version"]
|
|
assert_not_nil response.headers['X-Rule-Version']
|
|
end
|
|
|
|
test "should create event with valid DSN via Authorization header" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
end
|
|
|
|
test "should create event with valid DSN via X-Baffle-Auth header" do
|
|
post api_events_path,
|
|
headers: { "X-Baffle-Auth" => "Baffle baffle_key=#{@dsn.key}, baffle_version=1" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
end
|
|
|
|
test "should create event with valid DSN via Basic auth" do
|
|
credentials = Base64.strict_encode64("#{@dsn.key}:password")
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Basic #{credentials}" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
end
|
|
|
|
test "should create event with form encoded data" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: @sample_event_data,
|
|
as: :url_encoded
|
|
|
|
assert_response :success
|
|
end
|
|
|
|
test "should include rules in response when agent has no version" do
|
|
# Create some test rules
|
|
Rule.create!(action: "block", pattern_type: "ip", pattern: "192.168.1.0/24", reason: "Test rule")
|
|
Rule.create!(action: "allow", pattern_type: "ip", pattern: "10.0.0.0/8", reason: "Allow internal")
|
|
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
assert json_response["rules_changed"]
|
|
assert_not_nil json_response["rules"]
|
|
assert_equal 2, json_response["rules"].length
|
|
end
|
|
|
|
test "should include only new rules when agent has old version" do
|
|
# Create rules with different versions
|
|
old_rule = Rule.create!(action: "block", pattern_type: "ip", pattern: "192.168.1.0/24", reason: "Old rule", version: 1)
|
|
new_rule = Rule.create!(action: "block", pattern_type: "ip", pattern: "203.0.113.0/24", reason: "New rule", version: 2)
|
|
|
|
event_data_with_version = @sample_event_data.merge("last_rule_sync" => 1)
|
|
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: event_data_with_version,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
assert json_response["rules_changed"]
|
|
assert_equal 1, json_response["rules"].length
|
|
assert_equal "203.0.113.0/24", json_response["rules"].first["pattern"]
|
|
end
|
|
|
|
test "should not include rules when agent has latest version" do
|
|
# Create a rule and get its version
|
|
rule = Rule.create!(action: "block", pattern_type: "ip", pattern: "192.168.1.0/24", reason: "Test rule")
|
|
latest_version = Rule.latest_version
|
|
|
|
event_data_with_latest_version = @sample_event_data.merge("last_rule_sync" => latest_version)
|
|
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: event_data_with_latest_version,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
assert_not json_response["rules_changed"]
|
|
assert_nil json_response["rules"]
|
|
end
|
|
|
|
test "should return unauthorized with invalid DSN key" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer invalid-key-1234567890abcdef" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :unauthorized
|
|
end
|
|
|
|
test "should return unauthorized with disabled DSN" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@disabled_dsn.key}" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :unauthorized
|
|
end
|
|
|
|
test "should return unauthorized with no authentication" do
|
|
post api_events_path,
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :unauthorized
|
|
end
|
|
|
|
test "should return bad request with invalid JSON" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: "invalid json {",
|
|
as: :json
|
|
|
|
assert_response :bad_request
|
|
end
|
|
|
|
test "should handle empty request body gracefully" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: {},
|
|
as: :json
|
|
|
|
assert_response :success
|
|
json_response = JSON.parse(response.body)
|
|
assert json_response["success"]
|
|
end
|
|
|
|
test "should set sampling headers in response" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
assert_not_nil response.headers['X-Sample-Rate']
|
|
assert_not_nil response.headers['X-Sample-Until']
|
|
end
|
|
|
|
test "should set rule version header in response" do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
assert_not_nil response.headers['X-Rule-Version']
|
|
assert_match /^\d+$/, response.headers['X-Rule-Version']
|
|
end
|
|
|
|
test "should handle large event payloads" do
|
|
large_payload = @sample_event_data.merge(
|
|
"large_field" => "x" * 10000, # 10KB of data
|
|
"headers" => { "user-agent" => "TestAgent", "accept" => "*/*" },
|
|
"custom_data" => Hash[*(1..100).map { |i| ["key#{i}", "value#{i}"] }.flatten]
|
|
)
|
|
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: large_payload,
|
|
as: :json
|
|
|
|
assert_response :success
|
|
end
|
|
|
|
test "should process event asynchronously" do
|
|
# Clear any existing jobs
|
|
ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
|
|
ActiveJob::Base.queue_adapter.perform_enqueued_jobs = false
|
|
|
|
assert_difference 'ProcessWafEventJob.jobs.count', 1 do
|
|
post api_events_path,
|
|
headers: { "Authorization" => "Bearer #{@dsn.key}" },
|
|
params: @sample_event_data,
|
|
as: :json
|
|
end
|
|
|
|
assert_response :success
|
|
end
|
|
end |