| /** |
| * 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 {Component, OnInit} from '@angular/core'; |
| import {KafkaService} from '../../service/kafka.service'; |
| import {Router, ActivatedRoute} from '@angular/router'; |
| import {KafkaTopic} from '../../model/kafka-topic'; |
| import {MetronAlerts} from '../../shared/metron-alerts'; |
| import {SensorParserConfigService} from '../../service/sensor-parser-config.service'; |
| import {StormService} from '../../service/storm.service'; |
| import {TopologyStatus} from '../../model/topology-status'; |
| import {SensorParserConfigHistoryService} from '../../service/sensor-parser-config-history.service'; |
| import {SensorParserConfigHistory} from '../../model/sensor-parser-config-history'; |
| import {SensorEnrichmentConfigService} from '../../service/sensor-enrichment-config.service'; |
| import {SensorEnrichmentConfig} from '../../model/sensor-enrichment-config'; |
| import {RiskLevelRule} from '../../model/risk-level-rule'; |
| import {HdfsService} from '../../service/hdfs.service'; |
| import {RestError} from '../../model/rest-error'; |
| import {GrokValidationService} from '../../service/grok-validation.service'; |
| import {SensorParserConfig} from '../../model/sensor-parser-config'; |
| |
| @Component({ |
| selector: 'metron-config-sensor-parser-readonly', |
| templateUrl: 'sensor-parser-config-readonly.component.html', |
| styleUrls: ['sensor-parser-config-readonly.component.scss'] |
| }) |
| export class SensorParserConfigReadonlyComponent implements OnInit { |
| |
| selectedSensorName: string; |
| startStopInProgress: boolean = false; |
| kafkaTopic: KafkaTopic = new KafkaTopic(); |
| sensorParserConfigHistory: SensorParserConfigHistory = new SensorParserConfigHistory(); |
| sensorParserConfig: SensorParserConfig = new SensorParserConfig(); |
| topologyStatus: TopologyStatus = new TopologyStatus(); |
| sensorEnrichmentConfig: SensorEnrichmentConfig = new SensorEnrichmentConfig(); |
| grokStatement: string = ''; |
| transformsConfigKeys: string[] = []; |
| transformsConfigMap: {} = {}; |
| rules: RiskLevelRule[] = []; |
| transformLinkText = 'show more'; |
| threatTriageLinkText = 'show more'; |
| |
| editViewMetaData: {label?: string, value?: string, type?: string, model?: string, boldTitle?: boolean}[] = [ |
| {type: 'SEPARATOR', model: '', value: ''}, |
| {label: 'PARSER', model: 'sensorParserConfigHistory', value: 'parserClassName'}, |
| {label: 'LAST UPDATED', model: 'sensorParserConfigHistory', value: 'modifiedByDate'}, |
| {label: 'LAST EDITOR', model: 'sensorParserConfigHistory', value: 'modifiedBy'}, |
| {label: 'STATE', model: 'topologyStatus', value: 'sensorStatus'}, |
| {label: 'ORIGINATOR', model: 'sensorParserConfigHistory', value: 'createdBy'}, |
| {label: 'CREATION DATE', model: 'sensorParserConfigHistory', value: 'createdDate'}, |
| |
| {type: 'SPACER', model: '', value: ''}, |
| |
| {label: 'STORM', model: 'topologyStatus', value: 'status', boldTitle: true}, |
| {label: 'LATENCY', model: 'topologyStatus', value: 'latency'}, |
| {label: 'THROUGHPUT', model: 'topologyStatus', value: 'throughput'}, |
| {label: 'EMITTED(10 MIN)', model: 'topologyStatus', value: 'emitted'}, |
| {label: 'ACKED(10 MIN)', model: 'topologyStatus', value: 'acked'}, |
| {label: 'NUM WORKERS', model: 'sensorParserConfig', value: 'numWorkers'}, |
| {label: 'NUM ACKERS', model: 'sensorParserConfig', value: 'numAckers'}, |
| {label: 'SPOUT PARALLELISM', model: 'sensorParserConfig', value: 'spoutParallelism'}, |
| {label: 'SPOUT NUM TASKS', model: 'sensorParserConfig', value: 'spoutNumTasks'}, |
| {label: 'PARSER PARALLELISM', model: 'sensorParserConfig', value: 'parserParallelism'}, |
| {label: 'PARSER NUM TASKS', model: 'sensorParserConfig', value: 'parserNumTasks'}, |
| {label: 'ERROR WRITER PARALLELISM', model: 'sensorParserConfig', value: 'errorWriterParallelism'}, |
| {label: 'ERROR NUM TASKS', model: 'sensorParserConfig', value: 'errorWriterNumTasks'}, |
| |
| {type: 'SPACER', model: '', value: ''}, |
| |
| {label: 'KAFKA', model: 'kafkaTopic', value: 'currentKafkaStatus', boldTitle: true}, |
| {label: 'PARTITONS', model: 'kafkaTopic', value: 'numPartitions'}, |
| {label: 'REPLICATION FACTOR', model: 'kafkaTopic', value: 'replicationFactor'}, |
| {type: 'SEPARATOR', model: '', value: ''}, |
| |
| {label: '', model: 'grokStatement', value: 'grokPattern'}, |
| |
| {type: 'TITLE', model: '', value: 'Schema'}, |
| {label: '', model: 'transforms', value: ''}, |
| {type: 'SEPARATOR', model: '', value: ''}, |
| |
| {type: 'TITLE', model: '', value: 'Threat Triage Rules'}, |
| {label: '', model: 'threatTriageRules', value: ''} |
| |
| ]; |
| |
| constructor(private sensorParserConfigHistoryService: SensorParserConfigHistoryService, |
| private sensorParserConfigService: SensorParserConfigService, |
| private sensorEnrichmentService: SensorEnrichmentConfigService, |
| private stormService: StormService, |
| private kafkaService: KafkaService, |
| private hdfsService: HdfsService, |
| private grokValidationService: GrokValidationService, |
| private activatedRoute: ActivatedRoute, private router: Router, |
| private metronAlerts: MetronAlerts) { |
| } |
| |
| getSensorInfo(): void { |
| this.sensorParserConfigHistoryService.get(this.selectedSensorName).subscribe( |
| (results: SensorParserConfigHistory) => { |
| this.sensorParserConfigHistory = results; |
| this.sensorParserConfig = this.sensorParserConfigHistory.config; |
| this.setGrokStatement(); |
| this.setTransformsConfigKeys(); |
| |
| let items = this.sensorParserConfigHistory.config.parserClassName.split('.'); |
| this.sensorParserConfigHistory['parserClassName'] = items[items.length - 1].replace('Basic', '').replace('Parser', ''); |
| |
| }); |
| } |
| |
| getSensorStatusService() { |
| this.stormService.getStatus(this.selectedSensorName).subscribe( |
| (results: TopologyStatus) => { |
| this.topologyStatus = results; |
| }, |
| error => { |
| this.topologyStatus.status = 'Stopped'; |
| }); |
| } |
| |
| getKafkaData(): void { |
| this.kafkaService.get(this.selectedSensorName).subscribe( |
| (results: KafkaTopic) => { |
| this.kafkaTopic = results; |
| this.kafkaService.sample(this.selectedSensorName).subscribe((sampleData: string) => { |
| this.kafkaTopic['currentKafkaStatus'] = (sampleData && sampleData.length > 0) ? 'Emitting' : 'Not Emitting'; |
| }, |
| error => { |
| this.kafkaTopic['currentKafkaStatus'] = 'Not Emitting'; |
| }); |
| }, error => { |
| this.kafkaTopic['currentKafkaStatus'] = 'No Kafka Topic'; |
| }); |
| } |
| |
| getEnrichmentData() { |
| this.sensorEnrichmentService.get(this.selectedSensorName).subscribe((sensorEnrichmentConfig) => { |
| this.sensorEnrichmentConfig = sensorEnrichmentConfig; |
| this.rules = sensorEnrichmentConfig.threatIntel.triageConfig.riskLevelRules; |
| }); |
| } |
| |
| getTopologyStatus(key: string): string { |
| if (key === 'latency') { |
| return this.topologyStatus.latency >= 0 ? (this.topologyStatus.latency + 's') : '-'; |
| } else if (key === 'throughput') { |
| return this.topologyStatus.throughput >= 0 ? ((Math.round(this.topologyStatus.throughput * 100) / 100) + 'kb/s') : '-'; |
| } else if (key === 'emitted') { |
| return this.topologyStatus.emitted >= 0 ? (this.topologyStatus.emitted + '') : '-'; |
| } else if (key === 'acked') { |
| return this.topologyStatus.acked >= 0 ? (this.topologyStatus.acked + '') : '-'; |
| } else if (key === 'sensorStatus') { |
| if (this.topologyStatus.status === 'ACTIVE') { |
| return 'Enabled'; |
| } else if (this.topologyStatus.status === 'INACTIVE') { |
| return 'Disabled'; |
| } else { |
| return '-'; |
| } |
| } else if (key === 'status') { |
| if (this.topologyStatus.status === 'ACTIVE') { |
| return 'Running'; |
| } else if (this.topologyStatus.status === 'INACTIVE') { |
| return 'Disabled'; |
| } else { |
| return 'Stopped'; |
| } |
| } |
| |
| return this.topologyStatus[key] ? this.topologyStatus[key] : '-'; |
| } |
| |
| ngOnInit() { |
| this.activatedRoute.params.subscribe(params => { |
| this.selectedSensorName = params['id']; |
| this.getData(); |
| }); |
| } |
| |
| getData() { |
| this.startStopInProgress = false; |
| |
| this.getSensorInfo(); |
| this.getSensorStatusService(); |
| this.getKafkaData(); |
| this.getEnrichmentData(); |
| } |
| |
| setGrokStatement() { |
| if (this.sensorParserConfigHistory.config && this.sensorParserConfigHistory.config.parserConfig) { |
| let path = this.sensorParserConfigHistory.config.parserConfig['grokPath']; |
| if (path) { |
| this.hdfsService.read(path).subscribe(contents => { |
| this.grokStatement = contents; |
| }, (hdfsError: RestError) => { |
| this.grokValidationService.getStatement(path).subscribe(contents => { |
| this.grokStatement = contents; |
| }, (grokError: RestError) => { |
| this.metronAlerts.showErrorMessage('Could not find grok statement in HDFS or classpath at ' + path); |
| }); |
| }); |
| } |
| } |
| } |
| |
| setTransformsConfigKeys() { |
| if (this.sensorParserConfigHistory.config && this.sensorParserConfigHistory.config.fieldTransformations && |
| this.sensorParserConfigHistory.config.fieldTransformations.length > 0) { |
| this.transformsConfigKeys = []; |
| for (let transforms of this.sensorParserConfigHistory.config.fieldTransformations) { |
| if (transforms.config) { |
| for (let key of Object.keys(transforms.config)) { |
| if (this.transformsConfigKeys.indexOf(key) === -1) { |
| this.transformsConfigMap[key] = []; |
| this.transformsConfigKeys.push(key); |
| } |
| this.transformsConfigMap[key].push(transforms.config[key]); |
| } |
| } |
| } |
| this.transformsConfigKeys = this.transformsConfigKeys.sort(); |
| } |
| } |
| |
| getTransformsOutput(): string { |
| if (this.sensorParserConfigHistory.config && this.sensorParserConfigHistory.config.fieldTransformations && |
| this.sensorParserConfigHistory.config.fieldTransformations.length > 0) { |
| let output = []; |
| for (let transforms of this.sensorParserConfigHistory.config.fieldTransformations) { |
| if (transforms.output) { |
| output = output.concat(transforms.output); |
| } |
| } |
| output = output.sort().filter(function(item, pos, self) { |
| return self.indexOf(item) === pos; |
| }); |
| |
| return output.join(', '); |
| } |
| |
| return '-'; |
| } |
| |
| goBack() { |
| this.router.navigateByUrl('/sensors'); |
| } |
| |
| onEditSensor() { |
| this.router.navigateByUrl('/sensors(dialog:sensors-config/' + this.selectedSensorName + ')'); |
| } |
| |
| onStartSensor() { |
| this.toggleStartStopInProgress(); |
| let name = this.selectedSensorName; |
| |
| this.stormService.startParser(name).subscribe(result => { |
| this.metronAlerts.showSuccessMessage('Started sensor ' + name); |
| this.toggleStartStopInProgress(); |
| this.getData(); |
| }, |
| error => { |
| this.metronAlerts.showErrorMessage('Unable to start sensor ' + name); |
| this.toggleStartStopInProgress(); |
| }); |
| } |
| |
| onStopSensor() { |
| this.toggleStartStopInProgress(); |
| |
| let name = this.selectedSensorName; |
| this.stormService.stopParser(name).subscribe(result => { |
| this.metronAlerts.showSuccessMessage('Stopped sensor ' + name); |
| this.toggleStartStopInProgress(); |
| this.getData(); |
| }, |
| error => { |
| this.metronAlerts.showErrorMessage('Unable to stop sensor ' + name); |
| this.toggleStartStopInProgress(); |
| }); |
| } |
| |
| onEnableSensor() { |
| this.toggleStartStopInProgress(); |
| |
| let name = this.selectedSensorName; |
| this.stormService.activateParser(name).subscribe(result => { |
| this.metronAlerts.showSuccessMessage('Enabled sensor ' + name); |
| this.toggleStartStopInProgress(); |
| this.getData(); |
| }, |
| error => { |
| this.metronAlerts.showErrorMessage('Unable to enabled sensor ' + name); |
| this.toggleStartStopInProgress(); |
| }); |
| } |
| |
| onDisableSensor() { |
| this.toggleStartStopInProgress(); |
| |
| let name = this.selectedSensorName; |
| this.stormService.deactivateParser(name).subscribe(result => { |
| this.metronAlerts.showSuccessMessage('Disabled sensor ' + name); |
| this.toggleStartStopInProgress(); |
| this.getData(); |
| }, |
| error => { |
| this.metronAlerts.showErrorMessage('Unable to disable sensor ' + name); |
| this.toggleStartStopInProgress(); |
| }); |
| } |
| |
| onDeleteSensor() { |
| this.toggleStartStopInProgress(); |
| |
| let name = this.selectedSensorName; |
| this.sensorParserConfigService.deleteSensorParserConfig(name).subscribe(result => { |
| this.metronAlerts.showSuccessMessage('Deleted sensor ' + name); |
| this.toggleStartStopInProgress(); |
| this.sensorParserConfigService.dataChangedSource.next([name]); |
| this.goBack(); |
| }, |
| error => { |
| this.metronAlerts.showErrorMessage('Unable to delete sensor ' + name); |
| this.toggleStartStopInProgress(); |
| }); |
| } |
| |
| toggleStartStopInProgress() { |
| this.startStopInProgress = !this.startStopInProgress; |
| } |
| |
| getRuleDisplayName(): string { |
| return this.rules.map(x => this.getDisplayName(x)).join(', '); |
| } |
| |
| getDisplayName(riskLevelRule: RiskLevelRule): string { |
| if (riskLevelRule.name) { |
| return riskLevelRule.name; |
| } else { |
| return riskLevelRule.rule ? riskLevelRule.rule : ''; |
| } |
| } |
| |
| toggleTransformLink() { |
| return this.transformLinkText = (this.transformLinkText === 'show more') ? 'show less' : 'show more'; |
| } |
| |
| toggleThreatTriageLink() { |
| return this.threatTriageLinkText = (this.threatTriageLinkText === 'show more') ? 'show less' : 'show more'; |
| } |
| |
| isStartHidden() { |
| return (this.topologyStatus.status === 'ACTIVE' || this.topologyStatus.status === 'INACTIVE'); |
| } |
| |
| isStopHidden() { |
| return ((this.topologyStatus.status === 'KILLED' || this.topologyStatus.status === 'Stopped')); |
| } |
| |
| isEnableHidden() { |
| return (this.topologyStatus.status === 'ACTIVE' || this.topologyStatus.status === 'KILLED' |
| || this.topologyStatus.status === 'Stopped'); |
| } |
| |
| isDisableHidden() { |
| return (this.topologyStatus.status === 'INACTIVE' || this.topologyStatus.status === 'KILLED' |
| || this.topologyStatus.status === 'Stopped'); |
| } |
| } |