Commit f590ba85 authored by Can Eldem's avatar Can Eldem Committed by Kerri Miller

Calculate fingerprint for alerts

Calculating fingerprint for Cilium alerts to
prevent Gitlab flooding with Cilium alerts
parent 86a5baf4
...@@ -6,13 +6,22 @@ module Gitlab ...@@ -6,13 +6,22 @@ module Gitlab
class Cilium < Gitlab::AlertManagement::Payload::Generic class Cilium < Gitlab::AlertManagement::Payload::Generic
DEFAULT_TITLE = 'New: Alert' DEFAULT_TITLE = 'New: Alert'
attribute :description, paths: %w(flow dropReasonDesc) attribute :description, paths: %w(flow verdict)
attribute :title, paths: %w(ciliumNetworkPolicy metadata name), fallback: -> { DEFAULT_TITLE } attribute :title, paths: %w(ciliumNetworkPolicy metadata name), fallback: -> { DEFAULT_TITLE }
attribute :gitlab_fingerprint, paths: %w(fingerprint)
def monitoring_tool def monitoring_tool
Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:cilium] Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:cilium]
end end
private
def plain_gitlab_fingerprint
fpayload = self.payload.deep_dup
fpayload = fpayload['flow'].except('time', 'Summary')
fpayload['l4']['TCP'].delete('flags') if fpayload.dig('l4', 'TCP', 'flags')
fpayload.to_s
end
end end
end end
end end
......
...@@ -4,26 +4,55 @@ FactoryBot.define do ...@@ -4,26 +4,55 @@ FactoryBot.define do
factory :network_alert_payload, class: Hash do factory :network_alert_payload, class: Hash do
initialize_with do initialize_with do
{ {
fingerprint: 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3', flow: {
flow: { time: '2021-02-02T18:04:21.213587449Z',
dropReasonDesc: "POLICY_DENIED" verdict: 'POLICY_DENIED',
dropReasonDesc: 123,
ethernet: { source: '56:b6:52:62:6b:68', destination: '3a:dc:e3:9a:55:11' },
IP: { source: '10.0.0.224', destination: '10.0.0.87', ipVersion: 'IPv4' },
l4: { TCP: { sourcePort: 38_794, destinationPort: 5000, flags: { SYN: nil } } },
source: {
ID: 799,
identity: 37_570,
namespace: 'gitlab-managed-apps',
labels: [
'k8s:app.kubernetes.io/component=controller',
'k8s:app=nginx-ingress'
],
podName: 'ingress-nginx-ingress-controller-7dd4d7474d-m95gd'
},
destination: {
ID: 259,
identity: 30_147,
namespace: 'agent-project-21-production',
labels: [
'k8s:app=production',
'k8s:io.cilium.k8s.namespace.labels.app.gitlab.com/app=root-agent-project'
],
podName: 'production-7b998ffb56-vvl68'
},
Type: 'L3_L4',
nodeName: 'minikube',
eventType: { type: 5 },
trafficDirection: 'INGRESS',
Summary: 'TCP Flags: SYN'
}, },
ciliumNetworkPolicy: { ciliumNetworkPolicy: {
kind: 'bla', kind: 'bla',
apiVersion: 'bla', apiVersion: 'bla',
metadata: { metadata: {
name: 'Cilium Alert', name: 'Cilium Alert',
generateName: 'generated NAme', generateName: 'generated NAme',
namespace: 'LocalGitlab', namespace: 'LocalGitlab',
selfLink: 'www.gitlab.com', selfLink: 'www.gitlab.com',
uid: '2d931510-d99f-494a-8c67-87feb05e1594', uid: '2d931510-d99f-494a-8c67-87feb05e1594',
resourceVersion: '23', resourceVersion: '23',
deletionGracePeriodSeconds: 42, deletionGracePeriodSeconds: 42,
clusterName: 'TestCluster' clusterName: 'TestCluster'
}, },
status: {} status: {}
} }
}.with_indifferent_access }.with_indifferent_access
end end
end end
end end
...@@ -13,6 +13,6 @@ RSpec.describe Gitlab::AlertManagement::Payload::Cilium do ...@@ -13,6 +13,6 @@ RSpec.describe Gitlab::AlertManagement::Payload::Cilium do
it 'parses cilium specific fields' do it 'parses cilium specific fields' do
expect(parsed_payload.title).to eq('Cilium Alert') expect(parsed_payload.title).to eq('Cilium Alert')
expect(parsed_payload.description).to eq('POLICY_DENIED') expect(parsed_payload.description).to eq('POLICY_DENIED')
expect(parsed_payload.gitlab_fingerprint).to eq('a94a8fe5ccb19ba61c4c0873d391e987982fbbd3') expect(parsed_payload.gitlab_fingerprint).to eq('b2ad2a791756abe01692270c6a846129a09891b3')
end end
end end
...@@ -67,17 +67,10 @@ RSpec.describe API::Internal::Kubernetes do ...@@ -67,17 +67,10 @@ RSpec.describe API::Internal::Kubernetes do
stub_licensed_features(cilium_alerts: true) stub_licensed_features(cilium_alerts: true)
end end
let(:payload) do let(:payload) { build(:network_alert_payload) }
{
alert: {
title: 'minimal',
message: 'network problem'
}
}
end
it 'returns success for valid alert payload' do it 'returns no_content for valid alert payload' do
send_request(params: payload, headers: { 'Authorization' => "Bearer #{agent_token.token}" }) send_request(params: { alert: payload }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(AlertManagement::Alert.count).to eq(1) expect(AlertManagement::Alert.count).to eq(1)
expect(AlertManagement::Alert.all.first.project).to eq(agent.project) expect(AlertManagement::Alert.all.first.project).to eq(agent.project)
...@@ -107,7 +100,7 @@ RSpec.describe API::Internal::Kubernetes do ...@@ -107,7 +100,7 @@ RSpec.describe API::Internal::Kubernetes do
end end
it 'returns success' do it 'returns success' do
send_request(params: payload, headers: { 'Authorization' => "Bearer #{agent_token.token}" }) send_request(params: { alert: payload }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)
end end
...@@ -118,7 +111,7 @@ RSpec.describe API::Internal::Kubernetes do ...@@ -118,7 +111,7 @@ RSpec.describe API::Internal::Kubernetes do
let(:payload) { { temp: {} } } let(:payload) { { temp: {} } }
it 'returns bad request' do it 'returns bad request' do
send_request(params: payload, headers: { 'Authorization' => "Bearer #{agent_token.token}" }) send_request(params: { alert: payload }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
end end
end end
...@@ -129,7 +122,7 @@ RSpec.describe API::Internal::Kubernetes do ...@@ -129,7 +122,7 @@ RSpec.describe API::Internal::Kubernetes do
end end
it 'returns forbidden for non licensed project' do it 'returns forbidden for non licensed project' do
send_request(params: payload, headers: { 'Authorization' => "Bearer #{agent_token.token}" }) send_request(params: { alert: payload }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:forbidden) expect(response).to have_gitlab_http_status(:forbidden)
end end
......
...@@ -26,16 +26,6 @@ RSpec.describe AlertManagement::NetworkAlertService do ...@@ -26,16 +26,6 @@ RSpec.describe AlertManagement::NetworkAlertService do
subject(:execute) { service.execute } subject(:execute) { service.execute }
context 'with minimal payload' do
let(:payload_raw) do
{}.with_indifferent_access
end
let(:payload) { ActionController::Parameters.new(payload_raw).permit! }
it_behaves_like 'creates an alert management alert'
end
context 'with valid payload' do context 'with valid payload' do
let(:payload_raw) { build(:network_alert_payload) } let(:payload_raw) { build(:network_alert_payload) }
...@@ -55,7 +45,7 @@ RSpec.describe AlertManagement::NetworkAlertService do ...@@ -55,7 +45,7 @@ RSpec.describe AlertManagement::NetworkAlertService do
ended_at: nil, ended_at: nil,
environment_id: nil, environment_id: nil,
events: 1, events: 1,
fingerprint: 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3', fingerprint: '89269ffa3902af37f036a77bc9ea57cdee3a52c2',
hosts: [], hosts: [],
issue_id: nil, issue_id: nil,
monitoring_tool: 'Cilium', monitoring_tool: 'Cilium',
...@@ -77,7 +67,7 @@ RSpec.describe AlertManagement::NetworkAlertService do ...@@ -77,7 +67,7 @@ RSpec.describe AlertManagement::NetworkAlertService do
let!(:alert) do let!(:alert) do
create( create(
:alert_management_alert, :alert_management_alert,
project: project, domain: :threat_monitoring, fingerprint: Digest::SHA1.hexdigest(fingerprint) project: project, domain: :threat_monitoring, fingerprint: '89269ffa3902af37f036a77bc9ea57cdee3a52c2'
) )
end end
...@@ -85,7 +75,7 @@ RSpec.describe AlertManagement::NetworkAlertService do ...@@ -85,7 +75,7 @@ RSpec.describe AlertManagement::NetworkAlertService do
end end
context 'existing alert with same fingerprint' do context 'existing alert with same fingerprint' do
let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) } let(:fingerprint_sha) { '89269ffa3902af37f036a77bc9ea57cdee3a52c2' }
let!(:alert) do let!(:alert) do
create(:alert_management_alert, domain: :threat_monitoring, project: project, fingerprint: fingerprint_sha) create(:alert_management_alert, domain: :threat_monitoring, project: project, fingerprint: fingerprint_sha)
end end
...@@ -167,9 +157,7 @@ RSpec.describe AlertManagement::NetworkAlertService do ...@@ -167,9 +157,7 @@ RSpec.describe AlertManagement::NetworkAlertService do
end end
context 'error duing save' do context 'error duing save' do
let(:payload_raw) do let(:payload_raw) { build(:network_alert_payload) }
{}.with_indifferent_access
end
let(:logger) { double(warn: {}) } let(:logger) { double(warn: {}) }
let(:payload) { ActionController::Parameters.new(payload_raw).permit! } let(:payload) { ActionController::Parameters.new(payload_raw).permit! }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment