Skip to content

Commit 656b505

Browse files
authored
Fixed Incident-response-automation-must-allow-to-run-in-default-agent (#396) (#407)
1 parent 72e21f4 commit 656b505

File tree

11 files changed

+263
-21
lines changed

11 files changed

+263
-21
lines changed

frontend/src/app/incident-response/shared/component/ir-create-rule/ir-create-rule.component.html

Lines changed: 88 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,50 @@
11
<app-utm-modal-header [name]="(rule?'Edit':'Create') + ' incident response automation'"></app-utm-modal-header>
2-
<div class="container-fluid p-3">
3-
<div class="d-flex flex-column justify-content-start align-items-start">
2+
<div class="container-fluid p-3 pt-5">
3+
<div class="d-flex flex-column justify-content-start align-items-start pb-3">
44
<div class="step-container wizard-step">
55
<div class="step">
6-
<span class="text-blue-800 font-weight-bold">
6+
<span class="text-blue-800 font-weight-bold step-title">
77
Automation
88
</span>
99
<div [ngClass]="isCompleted(1)?'step-success':step===1?'step-active':'step-inactive'"
1010
class="round-indicator">
11-
<i [ngClass]="isCompleted(1)?'icon-checkmark3':'icon-file-css'"></i>
11+
<i class="step-icon" [ngClass]="isCompleted(1)?'icon-checkmark3':'icon-file-css'"></i>
1212
</div>
1313
</div>
1414
<div class="step-link">
1515
<div class="line w-100"></div>
1616
</div>
1717
<div class="step">
18-
<span class="text-blue-800 font-weight-bold">
18+
<span class="text-blue-800 font-weight-bold step-title">
1919
Trigger
2020
</span>
2121
<div [ngClass]="isCompleted(2)?'step-success':step===2?'step-active':'step-inactive'"
2222
class="round-indicator">
23-
<i [ngClass]="isCompleted(2)?'icon-checkmark3':'icon-power2'"></i>
23+
<i class="step-icon" [ngClass]="isCompleted(2)?'icon-checkmark3':'icon-power2'"></i>
2424
</div>
2525
</div>
2626
<div class="step-link">
2727
<div class="line w-100"></div>
2828
</div>
2929
<div class="step">
30-
<span class="text-blue-800 font-weight-bold">
30+
<span class="text-blue-800 font-weight-bold step-title">
3131
Action
3232
</span>
3333
<div [ngClass]="isCompleted(3)?'step-success':step===3?'step-active':'step-inactive'"
3434
class="round-indicator">
35-
<i [ngClass]="isCompleted(3)?'icon-checkmark3':'icon-terminal'"></i>
35+
<i class="step-icon" [ngClass]="isCompleted(3)?'icon-checkmark3':'icon-terminal'"></i>
36+
</div>
37+
</div>
38+
<div class="step-link">
39+
<div class="line w-100"></div>
40+
</div>
41+
<div class="step">
42+
<span class="text-blue-800 font-weight-bold step-title">
43+
Summary
44+
</span>
45+
<div [ngClass]="isCompleted(4)?'step-success':step===3?'step-active':'step-inactive'"
46+
class="round-indicator">
47+
<i class="step-icon" [ngClass]="isCompleted(4)?'icon-checkmark3':'icon-eye'"></i>
3648
</div>
3749
</div>
3850
</div>
@@ -122,21 +134,22 @@
122134
placement="left"
123135
(click)="removeRuleCondition(i)"></i>
124136
</div>
125-
<div class="d-flex justify-content-between">
137+
<div class="d-flex justify-content-between pr-4">
126138
<div>
127139
<span *ngIf="ruleConditions.length === 0 || !ruleConditions.valid"
128140
class="text-danger-300 font-size-base">
129141
You must set at least one trigger condition
130142
</span>
131143
</div>
132-
<button class="btn utm-button utm-button-primary align-self-end" (click)="addRuleCondition()">Add
133-
condition
144+
<button class="btn utm-button btn-success align-self-end" (click)="addRuleCondition()">
145+
<i class="icon-plus22"></i>&nbsp;
146+
Add
134147
</button>
135148
</div>
136149
</div>
137150
</div>
138-
<div class="d-flex mt-3">
139-
<div class="d-flex flex-column w-30 mb-3 pr-2">
151+
<div class="d-flex mt-3 flex-column">
152+
<div class="col-12 p-0">
140153
<label class="pb-1" for="exclude">Agent platform is</label>
141154
<ng-select [clearable]="false"
142155
[items]="platforms"
@@ -149,7 +162,7 @@
149162
</ng-select>
150163
<app-formcontrol-error [formcontrol]="formRule.get('agentPlatform')"></app-formcontrol-error>
151164
</div>
152-
<div class="d-flex flex-column flex-grow-1 mb-3 pl-2">
165+
<!--<div class="d-flex flex-column flex-grow-1 mb-3 pl-2">
153166
<label class="pb-1" for="exclude">Exclude agents</label>
154167
<ng-select [clearable]="false"
155168
[items]="agents"
@@ -163,6 +176,59 @@
163176
bindLabel="assetName"
164177
id="exclude">
165178
</ng-select>
179+
</div>-->
180+
</div>
181+
<div class="d-flex mt-3 flex-column">
182+
<div class="col-12">
183+
<app-utm-toggle (toggleChange)="formRule.get('agentType').setValue($event)"
184+
[active]="formRule.get('agentType').value"
185+
[emitAtStart]="false"
186+
[customClass]="'pl-3'"
187+
[label]="'Select the agent handling strategy for the automation. By default, commands won\'t run on specified agents, even if the trigger conditions match. Alternatively, choose a default agent to run the automation if no other agent matches the criteria.'" class="mb-3"></app-utm-toggle>
188+
</div>
189+
</div>
190+
<div *ngIf="formRule.get('agentType').value" class="d-flex mt-3 flex-column">
191+
<div class="col-12 p-0">
192+
<label class="pb-1" for="exclude">Exclude agents</label>
193+
<ng-select [clearable]="false"
194+
[items]="agents"
195+
[placeholder]="'Select agents to exclude'"
196+
[loadingText]="'Loading agents...'"
197+
[virtualScroll]="true"
198+
[multiple]="true"
199+
formControlName="excludedAgents"
200+
(change)="onChangeExclude($event)"
201+
bindValue="assetName"
202+
bindLabel="assetName"
203+
id="exclude">
204+
</ng-select>
205+
</div>
206+
<div class="col-12 p-0">
207+
<div class="alert alert-info alert-styled-right mt-2 info-dismissible">
208+
<span class="font-weight-semibold">Info! </span>
209+
<span>Represents agents where the commands won't run, even if the trigger conditions match</span>
210+
</div>
211+
</div>
212+
</div>
213+
<div *ngIf="!formRule.get('agentType').value" class="d-flex mt-3 flex-column">
214+
<div class="col-12 p-0">
215+
<label class="pb-1" for="exclude">Default agents</label>
216+
<ng-select [clearable]="false"
217+
[items]="agents"
218+
[placeholder]="'Select agent'"
219+
[loadingText]="'Loading agents...'"
220+
[virtualScroll]="true"
221+
formControlName="defaultAgent"
222+
bindValue="assetName"
223+
bindLabel="assetName"
224+
id="deafult">
225+
</ng-select>
226+
</div>
227+
<div class="col-12 p-0">
228+
<div class="alert alert-info alert-styled-right mt-2 info-dismissible">
229+
<span class="font-weight-semibold">Info! </span>
230+
<span>Designates the agent to execute the automation when no other agent meets the criteria to serve as the runner for this automation.</span>
231+
</div>
166232
</div>
167233
</div>
168234
<div *ngIf="platforms.length === 0"
@@ -206,22 +272,28 @@
206272
<span>Warning! You may cause damage to the infrastructure and services of your organization, please review the automation command before saving it</span>
207273
</div>
208274
</div>
275+
276+
<div *ngIf="step===4" class="configure-step mt-3 mb-3">
277+
<app-ir-summary
278+
[formRule]="formRule">
279+
</app-ir-summary>
280+
</div>
209281
</form>
210282
<div class="button-container d-flex justify-content-end mt-3">
211283
<button (click)="backStep()" *ngIf="step > 1"
212284
class="btn utm-button utm-button-primary">
213285
<i class="icon-arrow-left22"></i>&nbsp;
214286
Back
215287
</button>
216-
<button (click)="nextStep()" *ngIf="step < 3"
288+
<button (click)="nextStep()" *ngIf="step < 4"
217289
[disabled]="isDisable(step) "
218290
class="btn utm-button utm-button-primary ml-2">
219291
Next&nbsp;
220292
<i class="icon-arrow-right22"></i>
221293
</button>
222294

223295
<button (click)="createRule()"
224-
*ngIf="step===3"
296+
*ngIf="step===4"
225297
[disabled]="!command || command === ''"
226298
class="btn utm-button utm-button-primary ml-2">
227299
<i [ngClass]="creating?'icon-spinner2 spinner':'icon-terminal'"></i>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
1+
.step-title {
2+
position: absolute;
3+
bottom: 35px;
4+
}
15

6+
.wizard-step .step-link {
7+
padding-top: 0 !important;
8+
}
9+
10+
.step-icon {
11+
position: absolute;
12+
top:50%;
13+
transform: translateY(-50%);
14+
}

frontend/src/app/incident-response/shared/component/ir-create-rule/ir-create-rule.component.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ export class IrCreateRuleComponent implements OnInit {
5454
conditions: this.fb.array([]),
5555
command: ['', Validators.required],
5656
active: [true],
57+
agentType: [true],
5758
excludedAgents: [[]],
59+
defaultAgent: [''],
5860
agentPlatform: ['', Validators.required]
5961
});
6062
this.getPlatforms();
@@ -79,6 +81,8 @@ export class IrCreateRuleComponent implements OnInit {
7981
this.ruleConditions.push(ruleCondition);
8082
this.getAgents(this.formRule.get('agentPlatform').value);
8183
this.formRule.get('excludedAgents').setValue(this.rule.excludedAgents);
84+
this.formRule.get('agentType').setValue(this.rule.excludedAgents.length > 0);
85+
this.formRule.get('defaultAgent').setValue(this.rule.defaultAgent);
8286
}
8387
} else if (this.alert) {
8488
const alertName = this.getValueFromAlert(ALERT_NAME_FIELD);
@@ -182,15 +186,18 @@ export class IrCreateRuleComponent implements OnInit {
182186
const action = 'created';
183187
const actionError = 'creating';
184188
this.formRule.get('command').setValue(this.command);
189+
this.clearAgentTypeSelection();
185190
this.setNameBeforeSave();
186191
this.incidentResponseRuleService.create(this.formRule.value).subscribe(() => {
187192
this.successSaved(action);
188193
}, () => this.errorSaving(actionError));
189194
}
190195

191196
editRule() {
197+
console.log('edit');
192198
const action = 'edited';
193199
const actionError = 'editing';
200+
this.clearAgentTypeSelection();
194201
this.formRule.get('command').setValue(this.command);
195202
this.setNameBeforeSave();
196203
this.incidentResponseRuleService.update(this.formRule.value).subscribe(() => {
@@ -208,7 +215,13 @@ export class IrCreateRuleComponent implements OnInit {
208215
this.formRule.get('name').setValue(this.rulePrefix + this.formRule.get('name').value);
209216
}
210217

211-
218+
clearAgentTypeSelection(){
219+
if (!this.formRule.get('agentType').value) {
220+
this.formRule.get('excludedAgents').setValue([]);
221+
} else {
222+
this.formRule.get('defaultAgent').setValue('');
223+
}
224+
}
212225
errorSaving(action: string) {
213226
const ruleName: string = this.formRule.get('name').value;
214227
this.formRule.get('name').setValue(this.replacePrefixInName(ruleName));
@@ -268,4 +281,8 @@ export class IrCreateRuleComponent implements OnInit {
268281
});
269282
}
270283

284+
onChangeToggle() {
285+
286+
}
287+
271288
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
2+
<div class="d-flex p-2 flex-column">
3+
<div>
4+
<p>
5+
The automation <strong>{{ automationName }}</strong> is designed to execute based on specific conditions.
6+
It will evaluate the following conditions:
7+
</p>
8+
9+
<div class="alert-details mb-1 mt-1"
10+
*ngFor="let condition of conditions">
11+
<span class="text-blue-800 font-weight-light has-minimum-width">{{getFieldName(condition.field)}}</span>&nbsp;
12+
<span class="font-weight-light font-weight-semibold">{{getFilterName(condition.operator)}}</span>&nbsp;
13+
<span class="">{{condition.value}}</span>&nbsp;
14+
</div>
15+
16+
<span>
17+
On agents operating on the <strong>{{ platform | capitalize }}</strong> platform.
18+
</span>
19+
20+
21+
<ng-container *ngIf="agentType">
22+
<span>
23+
Importantly, the automation excludes designated agents, such as
24+
</span>
25+
<span class="badge p-1 border-1 badge-flat font-weight-light border-info-800 text-info-800 mr-2 mb-2"
26+
*ngFor="let exclusion of excludedAgents">{{exclusion}}
27+
</span>
28+
</ng-container>
29+
30+
<ng-container *ngIf="!agentType">
31+
<span>
32+
In case none of the agents satisfy the specified conditions, the automation will smoothly revert and execute on the default agent,
33+
<span class="badge p-1 border-1 badge-flat font-weight-light border-info-800 text-info-800 mr-2 mb-2">
34+
{{ defaultAgent | uppercase}}.
35+
</span>
36+
<span>
37+
This guarantees a comprehensive and adaptable approach to the automation process.
38+
</span>
39+
</span>
40+
</ng-container>
41+
</div>
42+
<div class="alert-details w-100 d-flex justify-content-start align-items-start mb-2 flex-column">
43+
<span>
44+
Crucially, when these conditions are met, the automation will proceed to execute the following action:
45+
</span>
46+
<app-utm-code-view [code]="command" [allowCopy]="true"></app-utm-code-view>
47+
</div>
48+
</div>
49+
50+
<div class="d-flex p-0 flex-column">
51+
<div class="col-12 p-0">
52+
<div class="alert alert-info alert-styled-right mt-2 info-dismissible">
53+
<span class="font-weight-semibold">Info! </span>
54+
<span>Please carefully review all presented changes, such as this one, before saving. Any oversight may lead to potential damage to your infrastructure.</span>
55+
</div>
56+
</div>
57+
</div>

frontend/src/app/incident-response/shared/component/ir-summary/ir-summary.component.scss

Whitespace-only changes.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
2+
import {FormArray, FormGroup} from '@angular/forms';
3+
import {UtmToastService} from '../../../../shared/alert/utm-toast.service';
4+
import {INCIDENT_AUTOMATION_ALERT_FIELDS} from '../../../../shared/constants/alert/alert-field.constant';
5+
import {FILTER_OPERATORS} from '../../../../shared/constants/filter-operators.const';
6+
import {ElasticOperatorsEnum} from '../../../../shared/enums/elastic-operators.enum';
7+
import {IncidentResponseAssetService} from '../../services/incident-response-asset.service';
8+
import {IncidentResponseJobService} from '../../services/incident-response-job.service';
9+
10+
@Component({
11+
selector: 'app-ir-summary',
12+
templateUrl: './ir-summary.component.html',
13+
styleUrls: ['./ir-summary.component.scss']
14+
})
15+
export class IrSummaryComponent implements OnInit {
16+
@Input() formRule: FormGroup;
17+
@Output() jobCreated = new EventEmitter<string>();
18+
alertFields = INCIDENT_AUTOMATION_ALERT_FIELDS;
19+
20+
21+
constructor(private incidentResponseAssetService: IncidentResponseAssetService,
22+
public utmToastService: UtmToastService,
23+
private incidentResponseJobService: IncidentResponseJobService) {
24+
}
25+
26+
ngOnInit() {
27+
}
28+
29+
get automationName() {
30+
return this.formRule.get('name').value;
31+
}
32+
33+
get platform() {
34+
return this.formRule.get('agentPlatform').value;
35+
}
36+
37+
get defaultAgent() {
38+
return this.formRule.get('defaultAgent').value;
39+
}
40+
41+
get command() {
42+
return this.formRule.get('command').value;
43+
}
44+
45+
get agentType() {
46+
return this.formRule.get('agentType').value;
47+
}
48+
49+
get conditions() {
50+
return (this.formRule.get('conditions') as FormArray).value;
51+
}
52+
53+
get excludedAgents() {
54+
return this.formRule.get('excludedAgents').value;
55+
}
56+
57+
getFieldName(field: string): string {
58+
return INCIDENT_AUTOMATION_ALERT_FIELDS.filter(value => value.field === field)[0].label;
59+
}
60+
61+
getFilterName(operator: ElasticOperatorsEnum): string {
62+
const index = FILTER_OPERATORS.findIndex(value => value.operator === operator);
63+
if (index !== -1) {
64+
return FILTER_OPERATORS[index].name;
65+
} else {
66+
return operator;
67+
}
68+
}
69+
70+
}

0 commit comments

Comments
 (0)