Skip to content
Snippets Groups Projects
Verified Commit a1561642 authored by Lucas Charles's avatar Lucas Charles :speech_balloon:
Browse files

Add WAF anomalies controller

Adds controller for serving anomaly request summaries for WAF. Serves
requests with polling interval of 5000ms and reactive caching

Part of the work to complete #14707
parent 4c0689f0
No related branches found
No related tags found
No related merge requests found
Pipeline #106939563 failed
# frozen_string_literal: true
module Projects
module Security
class WafAnomaliesController < Projects::ApplicationController
include RenderServiceResults
POLLING_INTERVAL = 5_000
before_action :authorize_read_waf_anomalies!
def summary
Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
@environment = ::Environment.find(params.delete("environment_id"))
head :not_found unless @environment
result = anomaly_summary_service.execute
respond_to do |format|
if result.nil?
format.json { continue_polling_response }
elsif result[:status] == :success
format.json { render status: :ok, json: result }
else
format.json { render status: :bad_request, json: result }
end
end
end
private
def anomaly_summary_service
::Security::WafAnomalySummaryService.new(environment: @environment, **query_params)
end
def query_params
params.permit(:interval, :from, :to)
end
def authorize_read_waf_anomalies!
render_403 unless can?(current_user, :read_threat_monitoring, project)
end
end
end
end
......@@ -81,6 +81,12 @@
end
resources :audit_events, only: [:index]
namespace :security do
resources :waf_anomalies, only: [] do
get :summary, on: :collection
end
end
end
# End of the /-/ scope.
......
# frozen_string_literal: true
require 'spec_helper'
describe Projects::Security::WafAnomaliesController do
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository, group: group) }
let_it_be(:environment) { create(:environment, :with_review_app, project: project) }
let_it_be(:action_params) { { project_id: project, namespace_id: project.namespace, environment_id: environment } }
let(:es_client) { nil }
describe 'GET #summary' do
subject { get :summary, params: action_params, format: :json }
before do
stub_licensed_features(threat_monitoring: true)
sign_in(user)
allow(::Environment).to receive(:find) { environment }
end
before do
allow_next_instance_of(::Security::WafAnomalySummaryService) do |instance|
allow(instance).to receive(:elasticsearch_client).at_most(:twice) { es_client }
end
end
context 'with authenticated user' do
before do
group.add_developer(user)
end
context 'with elastic_stack' do
let(:es_client) { double(Elasticsearch::Client) }
before do
allow(es_client).to receive(:msearch) { { "responses" => [{}, {}] } }
end
it 'returns anomaly summary' do
subject
expect(response).to have_gitlab_http_status(200)
expect(json_response['total_traffic']).to eq(0)
expect(json_response['anomalous_traffic']).to eq(0)
expect(response).to match_response_schema('vulnerabilities/summary', dir: 'ee')
end
end
context 'without elastic_stack' do
it 'returns request to continue polling' do
subject
expect(response).to have_gitlab_http_status(204)
end
end
it 'sets a polling interval header' do
subject
expect(response).to have_gitlab_http_status(204)
expect(response.headers['Poll-Interval']).to eq('5000')
end
end
context 'with unauthenticated user' do
it 'returns unauthorized' do
subject
expect(response).to have_gitlab_http_status(403)
end
end
end
end
\ No newline at end of file
{
"type": "object",
"required" : [
"total_traffic",
"anomalous_traffic",
"history",
"interval",
"from",
"to",
"status"
],
"properties" : {
"total_traffic": { "type": "integer" },
"anomalous_traffic": { "type": "integer" },
"history": {
"nominal": { "type": ["array"] },
"anomalous": { "type": ["array"] }
},
"interval": { "type": "string" },
"from": { "type": "date" },
"to": { "type": "date" },
"status": { "type": "string", "enum": ["success", "failure"] }
},
"additionalProperties": false
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment