Skip to content

Commit cd0dc57

Browse files
committed
feat(crowdstrike): implement CrowdStrike integration guide and update logs display
Signed-off-by: Manuel Abascal <mjabascal10@gmail.com>
1 parent b59e62e commit cd0dc57

File tree

16 files changed

+253
-79
lines changed

16 files changed

+253
-79
lines changed

frontend/src/app/app-management/app-logs/app-logs.component.html

Lines changed: 71 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ <h6 class="card-title mb-0 text-uppercase label-header">
44
Application logs
55
</h6>
66
<div class="d-flex justify-content-center align-items-center">
7-
<!--<ng-select (change)="filterBySelect($event,'source')"
7+
<ng-select (change)="filterBySelect($event,'source')"
88
[clearable]="true"
99
[items]="sources"
1010
[searchable]="false"
1111
class="has-minimum-width mr-3"
1212
placeholder="Source"
1313
style="min-width: 100px"
14-
></ng-select>-->
15-
<ng-select (change)="filterBySelect($event,'log.severity')"
14+
></ng-select>
15+
<ng-select (change)="filterBySelect($event,'type')"
1616
[clearable]="true"
1717
[items]="types"
1818
[searchable]="false"
@@ -28,78 +28,78 @@ <h6 class="card-title mb-0 text-uppercase label-header">
2828
</app-elastic-filter-time>
2929
</div>
3030
</div>
31-
<div class="table-responsive resizable-table-responsive m-h-0">
32-
<table class="table text-nowrap">
33-
<thead>
34-
<tr>
35-
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
36-
Date&nbsp;
37-
</th>
38-
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
39-
Source&nbsp;
40-
</th>
41-
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
42-
Type&nbsp;
43-
</th>
44-
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
45-
Preview&nbsp;
46-
</th>
47-
</tr>
48-
</thead>
49-
<tbody *ngIf="logs && !loading">
50-
<tr (click)="message = log.log.msg" *ngFor="let log of logs" class="cursor-pointer">
51-
<td><span>{{log["@timestamp"]| date:'medium':'UTC'}}</span></td>
52-
<td>
53-
<span>{{'PANEL ( '+ log.dataSource + ' )'}}</span>
54-
</td>
55-
<td>
56-
<span [ngClass]="getClassByType(log.log.severity)"
31+
<div class="table-responsive resizable-table-responsive m-h-0">
32+
<table class="table text-nowrap">
33+
<thead>
34+
<tr>
35+
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
36+
Date&nbsp;
37+
</th>
38+
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
39+
Source&nbsp;
40+
</th>
41+
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
42+
Type&nbsp;
43+
</th>
44+
<th class="font-weight-semibold text-uppercase cursor-pointer w-25">
45+
Preview&nbsp;
46+
</th>
47+
</tr>
48+
</thead>
49+
<tbody *ngIf="logs && !loading">
50+
<tr (click)="message = log.message" *ngFor="let log of logs" class="cursor-pointer">
51+
<td><span>{{log["@timestamp"]| date:'medium':'UTC'}}</span></td>
52+
<td>
53+
<span>{{log.source}}</span>
54+
</td>
55+
<td>
56+
<span [ngClass]="getClassByType(log.type)"
5757
class="p-1 border-1 rounded">
58-
{{log.log.severity}}
58+
{{log.type}}
5959
</span>
60-
</td>
61-
<td>
62-
<span [ngClass]="getClassByType(log.log.msg)">
63-
{{getPreview(log.log.msg)}}
60+
</td>
61+
<td>
62+
<span [ngClass]="getClassByType(log.type)">
63+
{{getPreview(log.message)}}
6464
</span>
65-
</td>
66-
</tr>
67-
</tbody>
68-
<tbody *ngIf="(logs.length===0 && !loading)">
69-
<tr>
70-
<td colspan="5">
71-
<app-no-data-found></app-no-data-found>
72-
</td>
73-
</tr>
74-
</tbody>
75-
<tbody *ngIf="loading">
76-
<tr>
77-
<td colspan="5">
78-
<div class="p-5 d-flex justify-content-center align-items-center text-blue-800">
79-
<app-utm-spinner [height]="'35px'"
80-
[label]="'Loading logs'"
81-
[loading]="loading"
82-
[width]="'35px'">
83-
</app-utm-spinner>
84-
</div>
85-
</td>
86-
</tr>
87-
</tbody>
88-
</table>
89-
</div>
90-
<div *ngIf="logs && logs.length>0" class="py-3">
91-
<div class="row justify-content-center">
92-
<ngb-pagination
93-
(pageChange)="loadPage($event)"
94-
[(page)]="page"
95-
[boundaryLinks]="true"
96-
[collectionSize]="totalItems"
97-
[maxSize]="5"
98-
[pageSize]="itemsPerPage"
99-
[rotate]="true"
100-
[size]="'sm'"></ngb-pagination>
101-
</div>
65+
</td>
66+
</tr>
67+
</tbody>
68+
<tbody *ngIf="(logs.length===0 && !loading)">
69+
<tr>
70+
<td colspan="5">
71+
<app-no-data-found></app-no-data-found>
72+
</td>
73+
</tr>
74+
</tbody>
75+
<tbody *ngIf="loading">
76+
<tr>
77+
<td colspan="5">
78+
<div class="p-5 d-flex justify-content-center align-items-center text-blue-800">
79+
<app-utm-spinner [height]="'35px'"
80+
[label]="'Loading logs'"
81+
[loading]="loading"
82+
[width]="'35px'">
83+
</app-utm-spinner>
84+
</div>
85+
</td>
86+
</tr>
87+
</tbody>
88+
</table>
89+
</div>
90+
<div *ngIf="logs && logs.length>0" class="py-3">
91+
<div class="row justify-content-center">
92+
<ngb-pagination
93+
(pageChange)="loadPage($event)"
94+
[(page)]="page"
95+
[boundaryLinks]="true"
96+
[collectionSize]="totalItems"
97+
[maxSize]="5"
98+
[pageSize]="itemsPerPage"
99+
[rotate]="true"
100+
[size]="'sm'"></ngb-pagination>
102101
</div>
102+
</div>
103103
</div>
104104

105105
<div *ngIf="message" class="utm-right-container">

frontend/src/app/app-management/app-logs/app-logs.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ export class AppLogsComponent implements OnInit {
2727
req: { filters: ElasticFilterType[], index: string, top: number } = {
2828
filters: [
2929
{field: '@timestamp', operator: ElasticOperatorsEnum.IS_BETWEEN, value: ['now-7d', 'now']},
30-
{field: 'log.containerName.keyword', operator: ElasticOperatorsEnum.IS, value: 'utmstack_backend'}
31-
], index: 'v11-log-utmstack-*', top: 100000
30+
], index: 'v11-backend-logs', top: 100000
3231
};
3332
sources = ['PANEL', 'AGENT'];
3433
types = ['ERROR', 'WARNING', 'INFO'];
@@ -58,6 +57,7 @@ export class AppLogsComponent implements OnInit {
5857
private onSuccess(data, headers) {
5958
this.totalItems = headers.get('X-Total-Count');
6059
this.logs = data || [];
60+
console.log('Logs loaded:', this.logs);
6161
this.loading = false;
6262
}
6363

frontend/src/app/app-module/app-module.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import {ModuleIntegrationComponent} from './module-integration/module-integratio
6363
import {ModuleService} from './services/module.service';
6464
import {AppModuleSharedModule} from './shared/app-module-shared.module';
6565
import {GuideUtmstackComponent} from "./guides/guide-utmstack/guide-utmstack.component";
66+
import {GuideCrowdstrikeComponent} from "./guides/guide-crowdstrike/guide-crowdstrike.component";
6667

6768

6869
@NgModule({
@@ -121,7 +122,8 @@ import {GuideUtmstackComponent} from "./guides/guide-utmstack/guide-utmstack.com
121122
InstallLogCollectorComponent,
122123
AgentInstallSelectorComponent,
123124
OracleComponent,
124-
GuideUtmstackComponent
125+
GuideUtmstackComponent,
126+
GuideCrowdstrikeComponent
125127
],
126128
imports: [
127129
CommonModule,

frontend/src/app/app-module/conf/int-generic-group-config/int-generic-group-config.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
<label [for]="'sectionParam'+integrationConfig.id" class="pb-1 span-small-icon d-flex justify-content-between align-items-center">
8888
<span>
8989
<i [ngbTooltip]="'This param is required'"
90-
[ngClass]="!checkConfigValue(integrationConfig.confValue)?'text-danger':'text-success'"
90+
[ngClass]="integrationConfig.confRequired && !checkConfigValue(integrationConfig.confValue) ? 'text-danger' : 'text-success'"
9191
class="icon-circle2 mr-1"
9292
placement="auto"></i>
9393
{{integrationConfig.confName}}
@@ -147,7 +147,7 @@
147147
</app-utm-file-upload>
148148

149149
<small
150-
*ngIf="integrationConfig.confValue === '' || integrationConfig.confValue === null || integrationConfig.confValue=== undefined"
150+
*ngIf="integrationConfig.confRequired && (integrationConfig.confValue === '' || integrationConfig.confValue === null || integrationConfig.confValue=== undefined)"
151151
class="text-danger">
152152
Param {{integrationConfig.confName}} is required
153153
</small>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {COLLECTOR_MESSAGE, Step} from '../shared/step';
2+
3+
export const CROWDSTRIKE_STEPS: Step[] = [
4+
{
5+
id: '1',
6+
name: 'Open the main menu. Click the hamburger icon in the top‑left corner labeled "Open menu".' +
7+
'Navigate to API management. Select **Support and resources** then **API Clients and Keys**.',
8+
content: {
9+
id: 'stepContent1',
10+
images: [{
11+
alt: 'Open menu hamburger top-left',
12+
src: '../../../../assets/img/guides/crowdstrike/1.png',
13+
}]
14+
}
15+
},
16+
{
17+
id: '2',
18+
name: 'Create a new API client. Click **Create API Client**, ' +
19+
'provide a descriptive client name (used to identify event sources) and select the API scopes required for Event Streams.',
20+
content: {
21+
id: 'stepContent2',
22+
images: [{
23+
alt: 'Create API client form with name and scopes',
24+
src: '../../../../assets/img/guides/crowdstrike/2.png',
25+
}]
26+
}
27+
},
28+
{
29+
id: '3',
30+
name: 'Generate credentials. Click **Create** to generate the client credentials and endpoint information.',
31+
content: {
32+
id: 'stepContent3',
33+
images: [{
34+
alt: 'Create button to generate API credentials',
35+
src: '../../../../assets/img/guides/crowdstrike/3.png',
36+
}]
37+
}
38+
},
39+
{
40+
id: '4',
41+
name: 'Record the credentials securely. Note the **Client ID**, **Client Secret** and the **Base URL** for the selected region.',
42+
content: {
43+
id: 'stepContent4',
44+
images: [{
45+
alt: 'Screen showing Client ID Client Secret and Base URL',
46+
src: '../../../../assets/img/guides/crowdstrike/4.png',
47+
}]
48+
}
49+
},
50+
{
51+
id: '5',
52+
name: 'Insert information in the following inputs.You can add more than one CrowdStrike configuration by clicking on Add tenant button.',
53+
content: {
54+
id: 'stepContent5'
55+
}
56+
},
57+
{id: '6', name: 'Click on the button shown below, to activate the UTMStack features related to this integration',
58+
content: {
59+
id: 'stepContent6'
60+
}
61+
}
62+
];

frontend/src/app/app-module/guides/guide-crowdstrike/guide-crowdstrike.component.css

Whitespace-only changes.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<div class="w-100 h-100">
2+
<div class="card-header d-flex justify-content-between align-items-center">
3+
<h4 class="card-title mb-0 text-primary">
4+
CROWDSTRIKE FALCON INTEGRATION
5+
</h4>
6+
</div>
7+
8+
<div class="card-body">
9+
<div class="alert alert-warning alert-styled-right mb-3">
10+
The UTMStack AS400 Collector communicate over ports 9000, 9001 and 50051. Please make sure these ports are open.
11+
</div>
12+
<ol class="setup_list">
13+
<app-utm-list [items]="steps">
14+
<ng-template stepTemplateRef let-step>
15+
<li>
16+
<app-step>
17+
<span stepNumber>{{step.id}}</span>
18+
<div [innerHtml]="step.name"></div>
19+
<ng-container *ngIf="step.content">
20+
21+
<ng-template [ngIf]="step.content['images']">
22+
<app-utm-list [items]="step.content['images']">
23+
<ng-template stepTemplateRef let-image>
24+
<img [alt]="image.alt" class="step-img" [src]="image.src">
25+
</ng-template>
26+
</app-utm-list>
27+
</ng-template>
28+
29+
<ng-template [ngIf]="step.content.id === 'stepContent5'">
30+
<app-int-generic-group-config [moduleId]="integrationId"
31+
(configValidChange)="configValidChange($event)"
32+
[serverId]="serverId"></app-int-generic-group-config>
33+
</ng-template>
34+
35+
<ng-template [ngIf]="step.content.id === 'stepContent6'">
36+
<div class="mt-3">
37+
<app-app-module-activate-button [module]="module.CROWDSTRIKE"
38+
[type]="'integration'"
39+
[disabled]="configValidity"
40+
[serverId]="serverId">
41+
</app-app-module-activate-button>
42+
</div>
43+
</ng-template>
44+
45+
</ng-container>
46+
</app-step>
47+
</li>
48+
</ng-template>
49+
</app-utm-list>
50+
</ol>
51+
</div>
52+
</div>
53+
54+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {Component, Input, OnInit} from '@angular/core';
2+
import {UtmModulesEnum} from '../../shared/enum/utm-module.enum';
3+
import {Step} from '../shared/step';
4+
import {CROWDSTRIKE_STEPS} from './crowdstrike.steps';
5+
6+
@Component({
7+
selector: 'app-guide-crowdstrike',
8+
templateUrl: './guide-crowdstrike.component.html',
9+
styleUrls: ['./guide-crowdstrike.component.css']
10+
})
11+
export class GuideCrowdstrikeComponent implements OnInit {
12+
@Input() integrationId: number;
13+
module = UtmModulesEnum;
14+
@Input() serverId: number;
15+
configValidity = false;
16+
steps: Step[] = CROWDSTRIKE_STEPS;
17+
18+
constructor() {
19+
}
20+
21+
ngOnInit() {
22+
}
23+
24+
configValidChange($event: boolean) {
25+
this.configValidity = !$event;
26+
}
27+
28+
}

frontend/src/app/app-module/module-integration/module-integration.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@
176176
<app-guide-utmstack *ngSwitchCase="moduleEnum.UTMSTACK" [serverId]="serverId"
177177
[integrationId]="module.id"></app-guide-utmstack>
178178

179+
<app-guide-crowdstrike *ngSwitchCase="moduleEnum.CROWDSTRIKE" [serverId]="serverId"
180+
[integrationId]="module.id"></app-guide-crowdstrike>
181+
179182
<app-guide-soc-ai *ngSwitchCase="moduleEnum.SOC_AI" [serverId]="serverId"
180183
[integrationId]="module.id"></app-guide-soc-ai>
181184

frontend/src/app/app-module/shared/enum/utm-module.enum.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@ export enum UtmModulesEnum {
6969
SOC_AI = 'SOC_AI',
7070
ORACLE = 'ORACLE',
7171
SURICATA= 'SURICATA',
72-
UTMSTACK= 'UTMSTACK'
72+
UTMSTACK= 'UTMSTACK',
73+
CROWDSTRIKE= 'CROWDSTRIKE',
7374
}

0 commit comments

Comments
 (0)