Skip to content
Snippets Groups Projects
Verified Commit 45c66eca 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 38b958ab
No related branches found
No related tags found
1 merge request!22437Add WAF Anomalies Controller and summary endpoint
# 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 }
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
{
"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