Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
<app-utm-modal-header [name]="(rule?'Edit':'Create') + ' incident response automation'"></app-utm-modal-header>
<div class="container-fluid p-3">
<div class="d-flex flex-column justify-content-start align-items-start">
<div class="container-fluid p-3 pt-5">
<div class="d-flex flex-column justify-content-start align-items-start pb-3">
<div class="step-container wizard-step">
<div class="step">
<span class="text-blue-800 font-weight-bold">
<span class="text-blue-800 font-weight-bold step-title">
Automation
</span>
<div [ngClass]="isCompleted(1)?'step-success':step===1?'step-active':'step-inactive'"
class="round-indicator">
<i [ngClass]="isCompleted(1)?'icon-checkmark3':'icon-file-css'"></i>
<i class="step-icon" [ngClass]="isCompleted(1)?'icon-checkmark3':'icon-file-css'"></i>
</div>
</div>
<div class="step-link">
<div class="line w-100"></div>
</div>
<div class="step">
<span class="text-blue-800 font-weight-bold">
<span class="text-blue-800 font-weight-bold step-title">
Trigger
</span>
<div [ngClass]="isCompleted(2)?'step-success':step===2?'step-active':'step-inactive'"
class="round-indicator">
<i [ngClass]="isCompleted(2)?'icon-checkmark3':'icon-power2'"></i>
<i class="step-icon" [ngClass]="isCompleted(2)?'icon-checkmark3':'icon-power2'"></i>
</div>
</div>
<div class="step-link">
<div class="line w-100"></div>
</div>
<div class="step">
<span class="text-blue-800 font-weight-bold">
<span class="text-blue-800 font-weight-bold step-title">
Action
</span>
<div [ngClass]="isCompleted(3)?'step-success':step===3?'step-active':'step-inactive'"
class="round-indicator">
<i [ngClass]="isCompleted(3)?'icon-checkmark3':'icon-terminal'"></i>
<i class="step-icon" [ngClass]="isCompleted(3)?'icon-checkmark3':'icon-terminal'"></i>
</div>
</div>
<div class="step-link">
<div class="line w-100"></div>
</div>
<div class="step">
<span class="text-blue-800 font-weight-bold step-title">
Summary
</span>
<div [ngClass]="isCompleted(4)?'step-success':step===3?'step-active':'step-inactive'"
class="round-indicator">
<i class="step-icon" [ngClass]="isCompleted(4)?'icon-checkmark3':'icon-eye'"></i>
</div>
</div>
</div>
Expand Down Expand Up @@ -122,21 +134,22 @@
placement="left"
(click)="removeRuleCondition(i)"></i>
</div>
<div class="d-flex justify-content-between">
<div class="d-flex justify-content-between pr-4">
<div>
<span *ngIf="ruleConditions.length === 0 || !ruleConditions.valid"
class="text-danger-300 font-size-base">
You must set at least one trigger condition
</span>
</div>
<button class="btn utm-button utm-button-primary align-self-end" (click)="addRuleCondition()">Add
condition
<button class="btn utm-button btn-success align-self-end" (click)="addRuleCondition()">
<i class="icon-plus22"></i>&nbsp;
Add
</button>
</div>
</div>
</div>
<div class="d-flex mt-3">
<div class="d-flex flex-column w-30 mb-3 pr-2">
<div class="d-flex mt-3 flex-column">
<div class="col-12 p-0">
<label class="pb-1" for="exclude">Agent platform is</label>
<ng-select [clearable]="false"
[items]="platforms"
Expand All @@ -149,7 +162,7 @@
</ng-select>
<app-formcontrol-error [formcontrol]="formRule.get('agentPlatform')"></app-formcontrol-error>
</div>
<div class="d-flex flex-column flex-grow-1 mb-3 pl-2">
<!--<div class="d-flex flex-column flex-grow-1 mb-3 pl-2">
<label class="pb-1" for="exclude">Exclude agents</label>
<ng-select [clearable]="false"
[items]="agents"
Expand All @@ -163,6 +176,59 @@
bindLabel="assetName"
id="exclude">
</ng-select>
</div>-->
</div>
<div class="d-flex mt-3 flex-column">
<div class="col-12">
<app-utm-toggle (toggleChange)="formRule.get('agentType').setValue($event)"
[active]="formRule.get('agentType').value"
[emitAtStart]="false"
[customClass]="'pl-3'"
[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>
</div>
</div>
<div *ngIf="formRule.get('agentType').value" class="d-flex mt-3 flex-column">
<div class="col-12 p-0">
<label class="pb-1" for="exclude">Exclude agents</label>
<ng-select [clearable]="false"
[items]="agents"
[placeholder]="'Select agents to exclude'"
[loadingText]="'Loading agents...'"
[virtualScroll]="true"
[multiple]="true"
formControlName="excludedAgents"
(change)="onChangeExclude($event)"
bindValue="assetName"
bindLabel="assetName"
id="exclude">
</ng-select>
</div>
<div class="col-12 p-0">
<div class="alert alert-info alert-styled-right mt-2 info-dismissible">
<span class="font-weight-semibold">Info! </span>
<span>Represents agents where the commands won't run, even if the trigger conditions match</span>
</div>
</div>
</div>
<div *ngIf="!formRule.get('agentType').value" class="d-flex mt-3 flex-column">
<div class="col-12 p-0">
<label class="pb-1" for="exclude">Default agents</label>
<ng-select [clearable]="false"
[items]="agents"
[placeholder]="'Select agent'"
[loadingText]="'Loading agents...'"
[virtualScroll]="true"
formControlName="defaultAgent"
bindValue="assetName"
bindLabel="assetName"
id="deafult">
</ng-select>
</div>
<div class="col-12 p-0">
<div class="alert alert-info alert-styled-right mt-2 info-dismissible">
<span class="font-weight-semibold">Info! </span>
<span>Designates the agent to execute the automation when no other agent meets the criteria to serve as the runner for this automation.</span>
</div>
</div>
</div>
<div *ngIf="platforms.length === 0"
Expand Down Expand Up @@ -206,22 +272,28 @@
<span>Warning! You may cause damage to the infrastructure and services of your organization, please review the automation command before saving it</span>
</div>
</div>

<div *ngIf="step===4" class="configure-step mt-3 mb-3">
<app-ir-summary
[formRule]="formRule">
</app-ir-summary>
</div>
</form>
<div class="button-container d-flex justify-content-end mt-3">
<button (click)="backStep()" *ngIf="step > 1"
class="btn utm-button utm-button-primary">
<i class="icon-arrow-left22"></i>&nbsp;
Back
</button>
<button (click)="nextStep()" *ngIf="step < 3"
<button (click)="nextStep()" *ngIf="step < 4"
[disabled]="isDisable(step) "
class="btn utm-button utm-button-primary ml-2">
Next&nbsp;
<i class="icon-arrow-right22"></i>
</button>

<button (click)="createRule()"
*ngIf="step===3"
*ngIf="step===4"
[disabled]="!command || command === ''"
class="btn utm-button utm-button-primary ml-2">
<i [ngClass]="creating?'icon-spinner2 spinner':'icon-terminal'"></i>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
.step-title {
position: absolute;
bottom: 35px;
}

.wizard-step .step-link {
padding-top: 0 !important;
}

.step-icon {
position: absolute;
top:50%;
transform: translateY(-50%);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export class IrCreateRuleComponent implements OnInit {
conditions: this.fb.array([]),
command: ['', Validators.required],
active: [true],
agentType: [true],
excludedAgents: [[]],
defaultAgent: [''],
agentPlatform: ['', Validators.required]
});
this.getPlatforms();
Expand All @@ -79,6 +81,8 @@ export class IrCreateRuleComponent implements OnInit {
this.ruleConditions.push(ruleCondition);
this.getAgents(this.formRule.get('agentPlatform').value);
this.formRule.get('excludedAgents').setValue(this.rule.excludedAgents);
this.formRule.get('agentType').setValue(this.rule.excludedAgents.length > 0);
this.formRule.get('defaultAgent').setValue(this.rule.defaultAgent);
}
} else if (this.alert) {
const alertName = this.getValueFromAlert(ALERT_NAME_FIELD);
Expand Down Expand Up @@ -182,15 +186,18 @@ export class IrCreateRuleComponent implements OnInit {
const action = 'created';
const actionError = 'creating';
this.formRule.get('command').setValue(this.command);
this.clearAgentTypeSelection();
this.setNameBeforeSave();
this.incidentResponseRuleService.create(this.formRule.value).subscribe(() => {
this.successSaved(action);
}, () => this.errorSaving(actionError));
}

editRule() {
console.log('edit');
const action = 'edited';
const actionError = 'editing';
this.clearAgentTypeSelection();
this.formRule.get('command').setValue(this.command);
this.setNameBeforeSave();
this.incidentResponseRuleService.update(this.formRule.value).subscribe(() => {
Expand All @@ -208,7 +215,13 @@ export class IrCreateRuleComponent implements OnInit {
this.formRule.get('name').setValue(this.rulePrefix + this.formRule.get('name').value);
}


clearAgentTypeSelection(){
if (!this.formRule.get('agentType').value) {
this.formRule.get('excludedAgents').setValue([]);
} else {
this.formRule.get('defaultAgent').setValue('');
}
}
errorSaving(action: string) {
const ruleName: string = this.formRule.get('name').value;
this.formRule.get('name').setValue(this.replacePrefixInName(ruleName));
Expand Down Expand Up @@ -268,4 +281,8 @@ export class IrCreateRuleComponent implements OnInit {
});
}

onChangeToggle() {

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

<div class="d-flex p-2 flex-column">
<div>
<p>
The automation <strong>{{ automationName }}</strong> is designed to execute based on specific conditions.
It will evaluate the following conditions:
</p>

<div class="alert-details mb-1 mt-1"
*ngFor="let condition of conditions">
<span class="text-blue-800 font-weight-light has-minimum-width">{{getFieldName(condition.field)}}</span>&nbsp;
<span class="font-weight-light font-weight-semibold">{{getFilterName(condition.operator)}}</span>&nbsp;
<span class="">{{condition.value}}</span>&nbsp;
</div>

<span>
On agents operating on the <strong>{{ platform | capitalize }}</strong> platform.
</span>


<ng-container *ngIf="agentType">
<span>
Importantly, the automation excludes designated agents, such as
</span>
<span class="badge p-1 border-1 badge-flat font-weight-light border-info-800 text-info-800 mr-2 mb-2"
*ngFor="let exclusion of excludedAgents">{{exclusion}}
</span>
</ng-container>

<ng-container *ngIf="!agentType">
<span>
In case none of the agents satisfy the specified conditions, the automation will smoothly revert and execute on the default agent,
<span class="badge p-1 border-1 badge-flat font-weight-light border-info-800 text-info-800 mr-2 mb-2">
{{ defaultAgent | uppercase}}.
</span>
<span>
This guarantees a comprehensive and adaptable approach to the automation process.
</span>
</span>
</ng-container>
</div>
<div class="alert-details w-100 d-flex justify-content-start align-items-start mb-2 flex-column">
<span>
Crucially, when these conditions are met, the automation will proceed to execute the following action:
</span>
<app-utm-code-view [code]="command" [allowCopy]="true"></app-utm-code-view>
</div>
</div>

<div class="d-flex p-0 flex-column">
<div class="col-12 p-0">
<div class="alert alert-info alert-styled-right mt-2 info-dismissible">
<span class="font-weight-semibold">Info! </span>
<span>Please carefully review all presented changes, such as this one, before saving. Any oversight may lead to potential damage to your infrastructure.</span>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {FormArray, FormGroup} from '@angular/forms';
import {UtmToastService} from '../../../../shared/alert/utm-toast.service';
import {INCIDENT_AUTOMATION_ALERT_FIELDS} from '../../../../shared/constants/alert/alert-field.constant';
import {FILTER_OPERATORS} from '../../../../shared/constants/filter-operators.const';
import {ElasticOperatorsEnum} from '../../../../shared/enums/elastic-operators.enum';
import {IncidentResponseAssetService} from '../../services/incident-response-asset.service';
import {IncidentResponseJobService} from '../../services/incident-response-job.service';

@Component({
selector: 'app-ir-summary',
templateUrl: './ir-summary.component.html',
styleUrls: ['./ir-summary.component.scss']
})
export class IrSummaryComponent implements OnInit {
@Input() formRule: FormGroup;
@Output() jobCreated = new EventEmitter<string>();
alertFields = INCIDENT_AUTOMATION_ALERT_FIELDS;


constructor(private incidentResponseAssetService: IncidentResponseAssetService,
public utmToastService: UtmToastService,
private incidentResponseJobService: IncidentResponseJobService) {
}

ngOnInit() {
}

get automationName() {
return this.formRule.get('name').value;
}

get platform() {
return this.formRule.get('agentPlatform').value;
}

get defaultAgent() {
return this.formRule.get('defaultAgent').value;
}

get command() {
return this.formRule.get('command').value;
}

get agentType() {
return this.formRule.get('agentType').value;
}

get conditions() {
return (this.formRule.get('conditions') as FormArray).value;
}

get excludedAgents() {
return this.formRule.get('excludedAgents').value;
}

getFieldName(field: string): string {
return INCIDENT_AUTOMATION_ALERT_FIELDS.filter(value => value.field === field)[0].label;
}

getFilterName(operator: ElasticOperatorsEnum): string {
const index = FILTER_OPERATORS.findIndex(value => value.operator === operator);
if (index !== -1) {
return FILTER_OPERATORS[index].name;
} else {
return operator;
}
}

}
Loading