blob: d5f3d6709b163e0cc43d63b010010e8cedbd8afa [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Inject} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Router, ActivatedRoute, Params} from '@angular/router';
import {Http, RequestOptions, Response, ResponseOptions} from '@angular/http';
import {SensorParserConfigComponent, Pane, KafkaStatus} from './sensor-parser-config.component';
import {StellarService} from '../../service/stellar.service';
import {SensorParserConfigService} from '../../service/sensor-parser-config.service';
import {KafkaService} from '../../service/kafka.service';
import {KafkaTopic} from '../../model/kafka-topic';
import {GrokValidationService} from '../../service/grok-validation.service';
import {MetronAlerts} from '../../shared/metron-alerts';
import {SensorParserConfig} from '../../model/sensor-parser-config';
import {ParseMessageRequest} from '../../model/parse-message-request';
import {SensorParserContext} from '../../model/sensor-parser-context';
import {AuthenticationService} from '../../service/authentication.service';
import {FieldTransformer} from '../../model/field-transformer';
import {SensorParserConfigModule} from './sensor-parser-config.module';
import {SensorEnrichmentConfigService} from '../../service/sensor-enrichment-config.service';
import {SensorEnrichmentConfig} from '../../model/sensor-enrichment-config';
import {APP_CONFIG, METRON_REST_CONFIG} from '../../app.config';
import {IAppConfig} from '../../app.config.interface';
import {SensorIndexingConfigService} from '../../service/sensor-indexing-config.service';
import {IndexingConfigurations} from '../../model/sensor-indexing-config';
import '../../rxjs-operators';
import 'rxjs/add/observable/of';
import {HdfsService} from '../../service/hdfs.service';
import {RestError} from '../../model/rest-error';
import {RiskLevelRule} from '../../model/risk-level-rule';
class MockRouter {
navigateByUrl(url: string) {}
}
class MockActivatedRoute {
private name: string;
params: Observable<Params>;
setNameForTest(name: string) {
this.name = name;
this.params = Observable.create(observer => {
observer.next({id: this.name});
observer.complete();
});
}
}
class MockSensorParserConfigService extends SensorParserConfigService {
private name: string;
private sensorParserConfig: SensorParserConfig;
private parsedMessage: any;
private postedSensorParserConfig: SensorParserConfig;
private throwError: boolean;
constructor(private http2: Http, @Inject(APP_CONFIG) private config2: IAppConfig) {
super(http2, config2);
}
public post(name: string, sensorParserConfig: SensorParserConfig): Observable<SensorParserConfig> {
if (this.throwError) {
let error = new RestError();
error.message = 'SensorParserConfig post error';
return Observable.throw(error);
}
this.postedSensorParserConfig = sensorParserConfig;
return Observable.create(observer => {
observer.next(sensorParserConfig);
observer.complete();
});
}
public get(name: string): Observable<SensorParserConfig> {
return Observable.create(observer => {
observer.next(this.sensorParserConfig);
observer.complete();
});
}
public getAll(): Observable<{}> {
return Observable.create(observer => {
let results = {};
results[this.name] = this.sensorParserConfig;
observer.next(results);
observer.complete();
});
}
public getAvailableParsers(): Observable<{}> {
return Observable.create(observer => {
observer.next({
'Bro': 'org.apache.metron.parsers.bro.BasicBroParser',
'Grok': 'org.apache.metron.parsers.GrokParser'
});
observer.complete();
});
}
public parseMessage(parseMessageRequest: ParseMessageRequest): Observable<{}> {
return Observable.create(observer => {
observer.next(this.parsedMessage);
observer.complete();
});
}
public setSensorParserConfig(name: string, sensorParserConfig: SensorParserConfig) {
this.name = name;
this.sensorParserConfig = sensorParserConfig;
}
public setParsedMessage(parsedMessage: any) {
this.parsedMessage = parsedMessage;
}
public setThrowError(throwError: boolean) {
this.throwError = throwError;
}
public getPostedSensorParserConfig() {
return this.postedSensorParserConfig;
}
}
class MockSensorIndexingConfigService extends SensorIndexingConfigService {
private name: string;
private postedIndexingConfigurations: IndexingConfigurations;
private sensorIndexingConfig: IndexingConfigurations;
private throwError: boolean;
constructor(private http2: Http, @Inject(APP_CONFIG) private config2: IAppConfig) {
super(http2, config2);
}
public post(name: string, sensorIndexingConfig: IndexingConfigurations): Observable<IndexingConfigurations> {
if (this.throwError) {
let error = new RestError();
error.message = 'IndexingConfigurations post error';
return Observable.throw(error);
}
this.postedIndexingConfigurations = sensorIndexingConfig;
return Observable.create(observer => {
observer.next(sensorIndexingConfig);
observer.complete();
});
}
public get(name: string): Observable<IndexingConfigurations> {
if (this.sensorIndexingConfig === null) {
let error = new RestError();
error.message = 'IndexingConfigurations get error';
return Observable.throw(error);
}
return Observable.create(observer => {
if (name === this.name) {
observer.next(this.sensorIndexingConfig);
}
observer.complete();
});
}
public setSensorIndexingConfig(name: string, result: IndexingConfigurations) {
this.name = name;
this.sensorIndexingConfig = result;
}
public setThrowError(throwError: boolean) {
this.throwError = throwError;
}
public getPostedIndexingConfigurations(): IndexingConfigurations {
return this.postedIndexingConfigurations;
}
}
class MockKafkaService extends KafkaService {
private name: string;
private kafkaTopic: KafkaTopic;
private kafkaTopicForPost: KafkaTopic;
private sampleData = {'key1': 'value1', 'key2': 'value2'};
constructor(private http2: Http, @Inject(APP_CONFIG) private config2: IAppConfig) {
super(http2, config2);
}
public setKafkaTopic(name: string, kafkaTopic: KafkaTopic) {
this.name = name;
this.kafkaTopic = kafkaTopic;
}
public setSampleData(name: string, sampleData?: any) {
this.name = name;
this.sampleData = sampleData;
}
public sample(name: string): Observable<string> {
if (this.sampleData === null) {
return Observable.throw(new RestError());
}
return Observable.create(observer => {
if (name === this.name) {
observer.next(JSON.stringify(this.sampleData));
}
observer.complete();
});
}
public get(name: string): Observable<KafkaTopic> {
if (this.kafkaTopic === null) {
return Observable.throw(new RestError());
}
return Observable.create(observer => {
if (name === this.name) {
observer.next(this.kafkaTopic);
}
observer.complete();
});
}
public post(k: KafkaTopic): Observable<KafkaTopic> {
this.kafkaTopicForPost = k;
console.log('called post MockKafkaService: ' + this.kafkaTopicForPost);
return Observable.create(observer => {
observer.next({});
observer.complete();
});
}
public getKafkaTopicForPost(): KafkaTopic {
console.log('Called get MockKafkaService: ' + this.kafkaTopicForPost);
return this.kafkaTopicForPost;
}
}
class MockGrokValidationService extends GrokValidationService {
private path: string;
private contents: string;
constructor(private http2: Http, @Inject(APP_CONFIG) private config2: IAppConfig) {
super(http2, config2);
}
public setContents(path: string, contents: string) {
this.path = path;
this.contents = contents;
}
public list(): Observable<string[]> {
return Observable.create(observer => {
observer.next({
'BASE10NUM': '(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\\.[0-9]+)?)|(?:\\.[0-9]+)))',
'BASE16FLOAT': '\\b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\\.[0-9A-Fa-f]*)?)|(?:\\.[0-9A-Fa-f]+)))\\b',
'BASE16NUM': '(?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))',
'CISCOMAC': '(?:(?:[A-Fa-f0-9]{4}\\.){2}[A-Fa-f0-9]{4})',
'COMMONMAC': '(?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})',
'DATA': '.*?'
});
observer.complete();
});
}
public getStatement(path: string): Observable<string> {
if (this.contents === null) {
return Observable.throw('Error');
}
return Observable.create(observer => {
if (path === this.path) {
observer.next(this.contents);
}
observer.complete();
});
}
}
class MockHdfsService extends HdfsService {
private fileList: string[];
private path: string;
private contents: string;
private postedContents: string;
constructor(private http2: Http, @Inject(APP_CONFIG) private config2: IAppConfig) {
super(http2, config2);
}
public setFileList(path: string, fileList: string[]) {
this.path = path;
this.fileList = fileList;
}
public setContents(path: string, contents: string) {
this.path = path;
this.contents = contents;
}
public list(path: string): Observable<string[]> {
if (this.fileList === null) {
return Observable.throw('Error');
}
return Observable.create(observer => {
if (path === this.path) {
observer.next(this.fileList);
}
observer.complete();
});
}
public read(path: string): Observable<string> {
if (this.contents === null) {
return Observable.throw('Error');
}
return Observable.create(observer => {
if (path === this.path) {
observer.next(this.contents);
}
observer.complete();
});
}
public post(path: string, contents: string): Observable<{}> {
if (this.contents === null) {
let error = new RestError();
error.message = 'HDFS post Error';
return Observable.throw(error);
}
this.postedContents = contents;
return Observable.create(observer => {
observer.next(contents);
observer.complete();
});
}
public deleteFile(path: string): Observable<Response> {
return Observable.create(observer => {
observer.next({});
observer.complete();
});
}
public getPostedContents() {
return this.postedContents;
}
}
class MockAuthenticationService extends AuthenticationService {
constructor(private http2: Http, private router2: Router, @Inject(APP_CONFIG) private config2: IAppConfig) {
super(http2, router2, config2);
}
public getCurrentUser(options: RequestOptions): Observable<Response> {
let responseOptions: ResponseOptions = new ResponseOptions();
responseOptions.body = 'user';
let response: Response = new Response(responseOptions);
return Observable.of(response);
};
}
class MockTransformationValidationService extends StellarService {
private transformationValidationResult: any;
private transformationValidationForValidate: SensorParserContext;
constructor(private http2: Http, @Inject(APP_CONFIG) private config2: IAppConfig) {
super(http2, config2);
}
public setTransformationValidationResultForTest(transformationValidationResult: any): void {
this.transformationValidationResult = transformationValidationResult;
}
public getTransformationValidationForValidate(): SensorParserContext {
return this.transformationValidationForValidate;
}
public validate(t: SensorParserContext): Observable<{}> {
this.transformationValidationForValidate = t;
return Observable.create(observer => {
observer.next(this.transformationValidationResult);
observer.complete();
});
}
}
export class MockSensorEnrichmentConfigService {
private name: string;
private sensorEnrichmentConfig: SensorEnrichmentConfig;
private postedSensorEnrichmentConfig: SensorEnrichmentConfig;
private throwError: boolean;
public setSensorEnrichmentConfig(name: string, sensorEnrichmentConfig: SensorEnrichmentConfig) {
this.name = name;
this.sensorEnrichmentConfig = sensorEnrichmentConfig;
}
public get(name: string): Observable<SensorEnrichmentConfig> {
if (this.sensorEnrichmentConfig === null) {
let error = new RestError();
error.message = 'SensorEnrichmentConfig get error';
return Observable.throw(error);
}
return Observable.create(observer => {
if (name === this.name) {
observer.next(this.sensorEnrichmentConfig);
}
observer.complete();
});
}
public post(name: string, sensorEnrichmentConfig: SensorEnrichmentConfig): Observable<SensorEnrichmentConfig> {
if (this.throwError) {
let error = new RestError();
error.message = 'SensorEnrichmentConfig post error';
return Observable.throw(error);
}
this.postedSensorEnrichmentConfig = sensorEnrichmentConfig;
return Observable.create(observer => {
observer.next(sensorEnrichmentConfig);
observer.complete();
});
}
public setThrowError(throwError: boolean) {
this.throwError = throwError;
}
public getPostedSensorEnrichmentConfig() {
return this.postedSensorEnrichmentConfig;
}
}
describe('Component: SensorParserConfig', () => {
let component: SensorParserConfigComponent;
let fixture: ComponentFixture<SensorParserConfigComponent>;
let sensorParserConfigService: MockSensorParserConfigService;
let sensorEnrichmentConfigService: MockSensorEnrichmentConfigService;
let sensorIndexingConfigService: MockSensorIndexingConfigService;
let transformationValidationService: MockTransformationValidationService;
let kafkaService: MockKafkaService;
let hdfsService: MockHdfsService;
let grokValidationService: MockGrokValidationService;
let activatedRoute: MockActivatedRoute;
let metronAlerts: MetronAlerts;
let router: MockRouter;
let squidSensorParserConfig: any = {
'parserClassName': 'org.apache.metron.parsers.GrokParser',
'sensorTopic': 'squid',
'parserConfig': {
'grokPath': '/apps/metron/patterns/squid',
'patternLabel': 'SQUID_DELIMITED',
'timestampField': 'timestamp'
},
'fieldTransformations': [
{
'input': [],
'output': ['full_hostname', 'domain_without_subdomains', 'hostname'],
'transformation': 'STELLAR',
'config': {
'full_hostname': 'URL_TO_HOST(url)',
'domain_without_subdomains': 'DOMAIN_REMOVE_SUBDOMAINS(full_hostname)'
}
}
],
};
let squidSensorEnrichmentConfig = {
'enrichment': {
'fieldMap': {
'geo': ['ip_dst_addr'],
'host': ['ip_dst_addr'],
'whois': [],
'stellar': { 'config': { 'group1': {} }}
},
'fieldToTypeMap': {}, 'config': {}
},
'threatIntel': {
'threatIntel': {
'fieldMap': { 'hbaseThreatIntel': ['ip_dst_addr'] },
'fieldToTypeMap': { 'ip_dst_addr': ['malicious_ip'] }
}
}
};
let squidIndexingConfigurations = {
'hdfs': {
'index': 'squid',
'batchSize': 5,
'enabled': true
},
'elasticsearch': {
'index': 'squid',
'batchSize': 10,
'enabled': true
},
'solr': {
'index': 'squid',
'batchSize': 1,
'enabled': false
},
};
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [SensorParserConfigModule],
providers: [
MetronAlerts,
{provide: Http},
{provide: SensorParserConfigService, useClass: MockSensorParserConfigService},
{provide: SensorIndexingConfigService, useClass: MockSensorIndexingConfigService},
{provide: KafkaService, useClass: MockKafkaService},
{provide: HdfsService, useClass: MockHdfsService},
{provide: GrokValidationService, useClass: MockGrokValidationService},
{provide: StellarService, useClass: MockTransformationValidationService},
{provide: ActivatedRoute, useClass: MockActivatedRoute},
{provide: Router, useClass: MockRouter},
{provide: AuthenticationService, useClass: MockAuthenticationService},
{provide: SensorEnrichmentConfigService, useClass: MockSensorEnrichmentConfigService},
{provide: APP_CONFIG, useValue: METRON_REST_CONFIG}
]
}).compileComponents()
.then(() => {
fixture = TestBed.createComponent(SensorParserConfigComponent);
component = fixture.componentInstance;
sensorParserConfigService = fixture.debugElement.injector.get(SensorParserConfigService);
sensorIndexingConfigService = fixture.debugElement.injector.get(SensorIndexingConfigService);
transformationValidationService = fixture.debugElement.injector.get(StellarService);
kafkaService = fixture.debugElement.injector.get(KafkaService);
hdfsService = fixture.debugElement.injector.get(HdfsService);
grokValidationService = fixture.debugElement.injector.get(GrokValidationService);
sensorEnrichmentConfigService = fixture.debugElement.injector.get(SensorEnrichmentConfigService);
activatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
metronAlerts = fixture.debugElement.injector.get(MetronAlerts);
router = fixture.debugElement.injector.get(Router);
});
}));
it('should create an instance of SensorParserConfigComponent', async(() => {
expect(component).toBeDefined();
fixture.destroy();
}));
it('should handle ngOnInit', async(() => {
spyOn(component, 'init');
spyOn(component, 'createForms');
spyOn(component, 'getAvailableParsers');
activatedRoute.setNameForTest('squid');
component.ngOnInit();
expect(component.init).toHaveBeenCalledWith('squid');
expect(component.createForms).toHaveBeenCalled();
expect(component.getAvailableParsers).toHaveBeenCalled();
fixture.destroy();
}));
it('should createForms', async(() => {
component.sensorParserConfig = Object.assign(new SensorParserConfig(), squidSensorParserConfig);
component.createForms();
expect(Object.keys(component.sensorConfigForm.controls).length).toEqual(16);
expect(Object.keys(component.transformsValidationForm.controls).length).toEqual(2);
expect(component.showAdvancedParserConfiguration).toEqual(true);
component.sensorParserConfig.parserConfig = {};
component.showAdvancedParserConfiguration = false;
component.createForms();
expect(component.showAdvancedParserConfiguration).toEqual(false);
fixture.destroy();
}));
it('should getAvailableParsers', async(() => {
component.getAvailableParsers();
expect(component.availableParsers).toEqual({
'Bro': 'org.apache.metron.parsers.bro.BasicBroParser',
'Grok': 'org.apache.metron.parsers.GrokParser'
});
expect(component.availableParserNames).toEqual(['Bro', 'Grok']);
fixture.destroy();
}));
it('should init', async(() => {
sensorParserConfigService.setSensorParserConfig('squid', squidSensorParserConfig);
component.init('new');
let expectedSensorParserConfig = new SensorParserConfig();
expectedSensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser';
expect(component.sensorParserConfig).toEqual(expectedSensorParserConfig);
expect(component.sensorEnrichmentConfig).toEqual(new SensorEnrichmentConfig());
expect(component.indexingConfigurations).toEqual(new IndexingConfigurations());
expect(component.editMode).toEqual(false);
expect(component.currentSensors).toEqual(['squid']);
spyOn(component, 'getKafkaStatus');
let sensorParserConfig = Object.assign(new SensorParserConfig(), squidSensorParserConfig);
sensorParserConfigService.setSensorParserConfig('squid', sensorParserConfig);
sensorEnrichmentConfigService.setSensorEnrichmentConfig('squid',
Object.assign(new SensorEnrichmentConfig(), squidSensorEnrichmentConfig));
sensorIndexingConfigService.setSensorIndexingConfig('squid',
Object.assign(new IndexingConfigurations(), squidIndexingConfigurations));
hdfsService.setContents('/apps/metron/patterns/squid', 'SQUID_DELIMITED grok statement');
component.init('squid');
expect(component.sensorParserConfig).toEqual(Object.assign(new SensorParserConfig(), squidSensorParserConfig));
expect(component.sensorNameValid).toEqual(true);
expect(component.getKafkaStatus).toHaveBeenCalled();
expect(component.showAdvancedParserConfiguration).toEqual(true);
expect(component.grokStatement).toEqual('SQUID_DELIMITED grok statement');
expect(component.patternLabel).toEqual('SQUID_DELIMITED');
expect(component.sensorEnrichmentConfig).toEqual(Object.assign(new SensorEnrichmentConfig(), squidSensorEnrichmentConfig));
expect(component.indexingConfigurations).toEqual(Object.assign(new IndexingConfigurations(), squidIndexingConfigurations));
component.sensorParserConfig.parserConfig['grokPath'] = '/patterns/squid';
hdfsService.setContents('/patterns/squid', null);
grokValidationService.setContents('/patterns/squid', 'SQUID grok statement from classpath');
component.init('squid');
expect(component.grokStatement).toEqual('SQUID grok statement from classpath');
spyOn(metronAlerts, 'showErrorMessage');
sensorEnrichmentConfigService.setSensorEnrichmentConfig('squid', null);
component.init('squid');
expect(metronAlerts.showErrorMessage).toHaveBeenCalledWith('SensorEnrichmentConfig get error');
sensorIndexingConfigService.setSensorIndexingConfig('squid', null);
component.init('squid');
expect(metronAlerts.showErrorMessage).toHaveBeenCalledWith('IndexingConfigurations get error');
grokValidationService.setContents('/patterns/squid', null);
component.init('squid');
expect(metronAlerts.showErrorMessage).toHaveBeenCalledWith('Could not find grok statement in HDFS or classpath at /patterns/squid');
sensorParserConfig = new SensorParserConfig();
sensorParserConfig.sensorTopic = 'bro';
sensorParserConfigService.setSensorParserConfig('bro', sensorParserConfig);
component.showAdvancedParserConfiguration = false;
component.init('bro');
expect(component.showAdvancedParserConfiguration).toEqual(false);
fixture.destroy();
}));
it('should getMessagePrefix', async(() => {
component.getAvailableParsers();
expect(component.getMessagePrefix()).toEqual('Created');
component.editMode = true;
expect(component.getMessagePrefix()).toEqual('Modified');
fixture.destroy();
}));
it('should handle onSetKafkaTopic', async(() => {
spyOn(component, 'getKafkaStatus');
spyOn(component, 'isConfigValid');
component.onSetKafkaTopic();
expect(component.getKafkaStatus).not.toHaveBeenCalled();
expect(component.isConfigValid).toHaveBeenCalled();
component.sensorParserConfig.sensorTopic = 'bro';
component.onSetKafkaTopic();
expect(component.kafkaTopicValid).toEqual(true);
expect(component.getKafkaStatus).toHaveBeenCalled();
fixture.destroy();
}));
it('should handle onSetSensorName', async(() => {
spyOn(component, 'isConfigValid');
component.onSetSensorName();
expect(component.isConfigValid).toHaveBeenCalled();
expect(component.sensorNameValid).toEqual(false);
component.sensorName = 'squid';
component.currentSensors = ['squid'];
component.onSetSensorName();
expect(component.sensorNameUnique).toEqual(false);
expect(component.sensorNameValid).toEqual(false);
component.sensorName = 'squidUnique';
component.onSetSensorName();
expect(component.sensorNameUnique).toEqual(true);
expect(component.sensorNameValid).toEqual(true);
fixture.destroy();
}));
it('should handle onParserTypeChange', async(() => {
spyOn(component, 'hidePane');
spyOn(component, 'isConfigValid');
component.onParserTypeChange();
expect(component.hidePane).not.toHaveBeenCalled();
expect(component.isConfigValid).toHaveBeenCalled();
component.sensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser';
component.onParserTypeChange();
expect(component.parserClassValid).toEqual(true);
expect(component.hidePane).not.toHaveBeenCalled();
component.sensorParserConfig.parserClassName = 'org.apache.metron.parsers.bro.BasicBroParser';
component.onParserTypeChange();
expect(component.hidePane).toHaveBeenCalledWith(Pane.GROK);
fixture.destroy();
}));
it('should handle onGrokStatementChange', async(() => {
spyOn(component, 'isConfigValid');
component.onGrokStatementChange();
expect(component.grokStatementValid).toEqual(false);
expect(component.isConfigValid).toHaveBeenCalled();
component.grokStatement = 'grok statement';
component.onGrokStatementChange();
expect(component.grokStatementValid).toEqual(true);
fixture.destroy();
}));
it('should handle isConfigValid', async(() => {
component.isConfigValid();
expect(component.configValid).toEqual(false);
component.sensorNameValid = true;
component.kafkaTopicValid = true;
component.parserClassValid = true;
component.isConfigValid();
expect(component.configValid).toEqual(true);
component.sensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser';
component.isConfigValid();
expect(component.configValid).toEqual(false);
component.grokStatementValid = true;
component.isConfigValid();
expect(component.configValid).toEqual(true);
fixture.destroy();
}));
it('should getKafkaStatus', async(() => {
component.getKafkaStatus();
expect(component.currentKafkaStatus).toEqual(null);
component.sensorParserConfig.sensorTopic = 'squid';
kafkaService.setKafkaTopic('squid', null);
component.getKafkaStatus();
expect(component.currentKafkaStatus).toEqual(KafkaStatus.NO_TOPIC);
kafkaService.setKafkaTopic('squid', new KafkaTopic());
kafkaService.setSampleData('squid', null);
component.getKafkaStatus();
expect(component.currentKafkaStatus).toEqual(KafkaStatus.NOT_EMITTING);
kafkaService.setSampleData('squid', 'message');
component.getKafkaStatus();
expect(component.currentKafkaStatus).toEqual(KafkaStatus.EMITTING);
fixture.destroy();
}));
it('should getTransforms', async(() => {
expect(component.getTransforms()).toEqual('0 Transformations Applied');
component.sensorParserConfig.fieldTransformations.push(Object.assign(new FieldTransformer(), {'output': ['field1', 'field2']}));
component.sensorParserConfig.fieldTransformations.push(Object.assign(new FieldTransformer(), {'output': ['field3']}));
expect(component.getTransforms()).toEqual('3 Transformations Applied');
fixture.destroy();
}));
it('should handle onSaveGrokStatement', async(() => {
component.sensorName = 'squid';
component.onSaveGrokStatement('grok statement');
expect(component.grokStatement).toEqual('grok statement');
expect(component.sensorParserConfig.parserConfig['grokPath']).toEqual('/apps/metron/patterns/squid');
component.sensorParserConfig.parserConfig['grokPath'] = '/patterns/squid';
component.onSaveGrokStatement('grok statement');
expect(component.sensorParserConfig.parserConfig['grokPath']).toEqual('/apps/metron/patterns/squid');
component.sensorParserConfig.parserConfig['grokPath'] = '/custom/grok/path';
component.onSaveGrokStatement('grok statement');
expect(component.sensorParserConfig.parserConfig['grokPath']).toEqual('/custom/grok/path');
fixture.destroy();
}));
it('should onSavePatternLabel', async(() => {
component.onSavePatternLabel('PATTERN_LABEL');
expect(component.patternLabel).toEqual('PATTERN_LABEL');
expect(component.sensorParserConfig.parserConfig['patternLabel']).toEqual('PATTERN_LABEL');
fixture.destroy();
}));
it('should goBack', async(() => {
activatedRoute.setNameForTest('new');
router.navigateByUrl = jasmine.createSpy('navigateByUrl');
component.goBack();
expect(router.navigateByUrl).toHaveBeenCalledWith('/sensors');
fixture.destroy();
}));
it('should save sensor configuration', async(() => {
let fieldTransformer = Object.assign(new FieldTransformer(), {
'input': [],
'output': ['url_host'],
'transformation': 'MTL',
'config': {'url_host': 'TO_LOWER(URL_TO_HOST(url))'}
});
let sensorParserConfigSave: SensorParserConfig = new SensorParserConfig();
sensorParserConfigSave.sensorTopic = 'squid';
sensorParserConfigSave.parserClassName = 'org.apache.metron.parsers.GrokParser';
sensorParserConfigSave.parserConfig['grokPath'] = '/apps/metron/patterns/squid';
sensorParserConfigSave.fieldTransformations = [fieldTransformer];
activatedRoute.setNameForTest('new');
sensorParserConfigService.setThrowError(true);
spyOn(metronAlerts, 'showSuccessMessage');
spyOn(metronAlerts, 'showErrorMessage');
component.sensorParserConfig.sensorTopic = 'squid';
component.sensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser';
component.sensorParserConfig.parserConfig['grokPath'] = '/apps/metron/patterns/squid';
component.sensorParserConfig.fieldTransformations = [fieldTransformer];
component.onSave();
expect(metronAlerts.showErrorMessage['calls'].mostRecent().args[0])
.toEqual('Unable to save sensor config: SensorParserConfig post error');
component.sensorEnrichmentConfig = Object.assign(new SensorEnrichmentConfig(), squidSensorEnrichmentConfig);
component.indexingConfigurations = Object.assign(new IndexingConfigurations(), squidIndexingConfigurations);
sensorParserConfigService.setThrowError(false);
hdfsService.setContents('/apps/metron/patterns/squid', 'SQUID grok statement');
component.grokStatement = 'SQUID grok statement';
component.onSave();
expect(sensorParserConfigService.getPostedSensorParserConfig()).toEqual(sensorParserConfigSave);
expect(sensorEnrichmentConfigService.getPostedSensorEnrichmentConfig())
.toEqual(Object.assign(new SensorEnrichmentConfig(), squidSensorEnrichmentConfig));
expect(sensorIndexingConfigService.getPostedIndexingConfigurations())
.toEqual(Object.assign(new IndexingConfigurations(), squidIndexingConfigurations));
expect(hdfsService.getPostedContents()).toEqual('SQUID grok statement');
hdfsService.setContents('/apps/metron/patterns/squid', null);
component.onSave();
expect(metronAlerts.showErrorMessage['calls'].mostRecent().args[0]).toEqual('HDFS post Error');
sensorEnrichmentConfigService.setThrowError(true);
component.onSave();
expect(metronAlerts.showErrorMessage['calls'].mostRecent().args[0])
.toEqual('Created Sensor parser config but unable to save enrichment configuration: SensorEnrichmentConfig post error');
sensorIndexingConfigService.setThrowError(true);
component.onSave();
expect(metronAlerts.showErrorMessage['calls'].mostRecent().args[0])
.toEqual('Created Sensor parser config but unable to save indexing configuration: IndexingConfigurations post error');
fixture.destroy();
}));
it('should getTransformationCount', async(() => {
let transforms =
[
Object.assign(new FieldTransformer(), {
'input': [
'method'
],
'output': null,
'transformation': 'REMOVE',
'config': {
'condition': 'exists(method) and method == "foo"'
}
}),
Object.assign(new FieldTransformer(), {
'input': [],
'output': [
'method',
'status_code',
'url'
],
'transformation': 'STELLAR',
'config': {
'method': 'TO_UPPER(method)',
'status_code': 'TO_LOWER(code)',
'url': 'TO_STRING(TRIM(url))'
}
})
];
expect(component.getTransformationCount()).toEqual(0);
fixture.componentInstance.sensorParserConfig.fieldTransformations = transforms;
expect(component.getTransformationCount()).toEqual(3);
fixture.componentInstance.sensorParserConfig.fieldTransformations = [transforms[0]];
expect(component.getTransformationCount()).toEqual(0);
fixture.destroy();
}));
it('should getEnrichmentCount', async(() => {
component.sensorEnrichmentConfig.enrichment.fieldMap['geo'] = ['ip_src_addr', 'ip_dst_addr'];
component.sensorEnrichmentConfig.enrichment.fieldToTypeMap['hbaseenrichment'] = ['ip_src_addr', 'ip_dst_addr'];
expect(component.getEnrichmentCount()).toEqual(4);
fixture.destroy();
}));
it('should getThreatIntelCount', async(() => {
component.sensorEnrichmentConfig.threatIntel.fieldToTypeMap['hbaseenrichment'] = ['ip_src_addr', 'ip_dst_addr'];
expect(component.getThreatIntelCount()).toEqual(2);
fixture.destroy();
}));
it('should getRuleCount', async(() => {
let rule1 = Object.assign(new RiskLevelRule(), {'name': 'rule1', 'rule': 'some rule', 'score': 50});
let rule2 = Object.assign(new RiskLevelRule(), {'name': 'rule2', 'rule': 'some other rule', 'score': 80});
component.sensorEnrichmentConfig.threatIntel.triageConfig.riskLevelRules.push(rule1);
component.sensorEnrichmentConfig.threatIntel.triageConfig.riskLevelRules.push(rule2);
expect(component.getRuleCount()).toEqual(2);
fixture.destroy();
}));
it('should showPane', async(() => {
component.showPane(Pane.GROK);
expect(component.showGrokValidator).toEqual(true);
expect(component.showFieldSchema).toEqual(false);
expect(component.showRawJson).toEqual(false);
component.showPane(Pane.FIELDSCHEMA);
expect(component.showGrokValidator).toEqual(false);
expect(component.showFieldSchema).toEqual(true);
expect(component.showRawJson).toEqual(false);
component.showPane(Pane.RAWJSON);
expect(component.showGrokValidator).toEqual(false);
expect(component.showFieldSchema).toEqual(false);
expect(component.showRawJson).toEqual(true);
fixture.destroy();
}));
it('should hidePane', async(() => {
component.hidePane(Pane.GROK);
expect(component.showGrokValidator).toEqual(false);
expect(component.showFieldSchema).toEqual(false);
expect(component.showRawJson).toEqual(false);
component.hidePane(Pane.FIELDSCHEMA);
expect(component.showGrokValidator).toEqual(false);
expect(component.showFieldSchema).toEqual(false);
expect(component.showRawJson).toEqual(false);
component.hidePane(Pane.RAWJSON);
expect(component.showGrokValidator).toEqual(false);
expect(component.showFieldSchema).toEqual(false);
expect(component.showRawJson).toEqual(false);
fixture.destroy();
}));
it('should handle onShowGrokPane', async(() => {
spyOn(component, 'showPane');
component.sensorName = 'squid';
component.onShowGrokPane();
expect(component.patternLabel).toEqual('SQUID');
expect(component.showPane).toHaveBeenCalledWith(component.pane.GROK);
component.patternLabel = 'PATTERN_LABEL';
component.onShowGrokPane();
expect(component.patternLabel).toEqual('PATTERN_LABEL');
fixture.destroy();
}));
it('should handle onRawJsonChanged', async(() => {
spyOn(component.sensorFieldSchema, 'createFieldSchemaRows');
component.onRawJsonChanged();
expect(component.sensorFieldSchema.createFieldSchemaRows).toHaveBeenCalled();
fixture.destroy();
}));
it('should handle onAdvancedConfigFormClose', async(() => {
component.onAdvancedConfigFormClose();
expect(component.showAdvancedParserConfiguration).toEqual(false);
fixture.destroy();
}));
});