Repository: metron Updated Branches: refs/heads/master e3900c4db -> cd7257e12
http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/e2e/mock-data/alerts_ui_e2e_index.template ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/mock-data/alerts_ui_e2e_index.template b/metron-interface/metron-alerts/e2e/mock-data/alerts_ui_e2e_index.template new file mode 100644 index 0000000..7737592 --- /dev/null +++ b/metron-interface/metron-alerts/e2e/mock-data/alerts_ui_e2e_index.template @@ -0,0 +1,975 @@ +{ + "template": "alerts_ui_e2e_index", + "mappings": { + "alerts_ui_e2e_doc": { + "_timestamp": { + "enabled": true + }, + "dynamic_templates": [ + { + "geo_location_point": { + "match": "enrichments:geo:*:location_point", + "match_mapping_type": "*", + "mapping": { + "type": "geo_point" + } + } + }, + { + "geo_country": { + "match": "enrichments:geo:*:country", + "match_mapping_type": "*", + "mapping": { + "type": "string", + "index": "not_analyzed" + } + } + }, + { + "geo_city": { + "match": "enrichments:geo:*:city", + "match_mapping_type": "*", + "mapping": { + "type": "string", + "index": "not_analyzed" + } + } + }, + { + "geo_location_id": { + "match": "enrichments:geo:*:locID", + "match_mapping_type": "*", + "mapping": { + "type": "string", + "index": "not_analyzed" + } + } + }, + { + "geo_dma_code": { + "match": "enrichments:geo:*:dmaCode", + "match_mapping_type": "*", + "mapping": { + "type": "string", + "index": "not_analyzed" + } + } + }, + { + "geo_postal_code": { + "match": "enrichments:geo:*:postalCode", + "match_mapping_type": "*", + "mapping": { + "type": "string", + "index": "not_analyzed" + } + } + }, + { + "geo_latitude": { + "match": "enrichments:geo:*:latitude", + "match_mapping_type": "*", + "mapping": { + "type": "float" + } + } + }, + { + "geo_longitude": { + "match": "enrichments:geo:*:longitude", + "match_mapping_type": "*", + "mapping": { + "type": "float" + } + } + }, + { + "timestamps": { + "match": "*:ts", + "match_mapping_type": "*", + "mapping": { + "type": "date", + "format": "epoch_millis" + } + } + }, + { + "threat_triage_score": { + "mapping": { + "type": "float" + }, + "match": "threat.triage.rules:*:score", + "match_mapping_type": "*" + } + }, + { + "threat_triage_reason": { + "mapping": { + "type": "string" + }, + "match": "threat.triage.rules:*:reason", + "match_mapping_type": "*" + } + }, + { + "threat_triage_name": { + "mapping": { + "type": "string" + }, + "match": "threat.triage.rules:*:name", + "match_mapping_type": "*" + } + } + ], + "properties": { + /* + * WARNING + * + * Because Metron inserts many distinct bro records into a single ElasticSearch index + * by default, it encounters field collisions due to field name reuse across bro logs. + * + * Be careful when modifying this file to not unintentionally affect other logs. + * For instance, the "version" field exists in the HTTP, SSL, and SSH logs. If you + * were to only consider the SSH log, you would set the type to integer, but because + * in the SSL and HTTP logs version is a string, we must set the type to string. + */ + /* + * Metron-specific fields + */ + "source:type": { + "type": "string", + "index": "not_analyzed" + }, + /* + * Widely-used Bro fields (potentially renamed during Metron ingest) + */ + "timestamp": { + "type": "date", + "format": "epoch_millis" + }, + "uid": { + "type": "string", + "index": "not_analyzed" + }, + "alert": { + "type": "nested" + }, + "ip_src_addr": { + "type": "ip" + }, + "ip_src_port": { + "type": "integer" + }, + "ip_dst_addr": { + "type": "ip" + }, + "ip_dst_port": { + "type": "integer" + }, + /* + * HTTP log support + * https://www.bro.org/sphinx/scripts/base/protocols/http/main.bro.html#type-HTTP::Info + * + * Notable Fields + * Field: password + * Notes: Field exists in the HTTP and FTP logs + * + * Field: capture_password + * Notes: Field exists in the HTTP and FTP logs + * + * Field: trans_depth + * Notes: Field exists in the HTTP and SMTP logs + * + * Field: user_agent + * Notes: Field exists in the HTTP and SMTP logs + * + * Field: version + * Notes: Field exists in the HTTP, SSL, and SSH logs + * + * Field: host + * Notes: Field exists in the HTTP and Software logs + * + * Field: username + * Notes: Field exists in the HTTP and RADIUS logs + */ + "trans_depth": { + "type": "integer" + }, + "method": { + "type": "string", + "index": "not_analyzed" + }, + "host": { + "type": "string", + "index": "not_analyzed" + }, + "uri": { + "type": "string", + "index": "not_analyzed", + "ignore_above": 8191 + }, + "referrer": { + "type": "string", + "index": "not_analyzed" + }, + "version": { + "type": "string", + "index": "not_analyzed" + }, + "user_agent": { + "type": "string" + }, + "request_body_len": { + "type": "long" + }, + "response_body_len": { + "type": "long" + }, + "status_code": { + "type": "integer" + }, + "status_msg": { + "type": "string", + "index": "not_analyzed" + }, + "username": { + "type": "string", + "index": "not_analyzed" + }, + "password": { + "type": "string", + "index": "not_analyzed" + }, + "capture_password": { + "type": "boolean" + }, + /* + * DNS log support + * https://www.bro.org/sphinx/scripts/base/protocols/dns/main.bro.html#type-DNS::Info + * + * Notable Fields + * Field: proto + * Notes: Field exists in the DNS, Conn, DPD, and Notice logs + * + * Field: trans_id + * Notes: Field exists in the DNS and DHCP logs + */ + "proto": { + "type": "string", + "index": "not_analyzed" + }, + "trans_id": { + "type": "long" + }, + "query": { + "type": "string", + "index": "not_analyzed" + }, + "qclass": { + "type": "integer" + }, + "qclass_name": { + "type": "string", + "index": "not_analyzed" + }, + "qtype": { + "type": "integer" + }, + "qtype_name": { + "type": "string", + "index": "not_analyzed" + }, + "rcode": { + "type": "integer" + }, + "rcode_name": { + "type": "string", + "index": "not_analyzed" + }, + "AA": { + "type": "boolean" + }, + "TC": { + "type": "boolean" + }, + "RD": { + "type": "boolean" + }, + "RA": { + "type": "boolean" + }, + "Z": { + "type": "integer" + }, + "answers": { + "type": "string" + }, + "rejected": { + "type": "boolean" + }, + /* + * Conn log support + * https://www.bro.org/sphinx/scripts/base/protocols/conn/main.bro.html#type-Conn::Info + * + * Notable Fields + * Field: proto + * Notes: Field exists in the DNS, Conn, DPD, and Notice logs + * + * Field: duration + * Notes: Field exists in the Conn and Files logs + * + * Field: local_orig + * Notes: Field exists in the Conn and Files logs + */ + "service": { + "type": "string", + "index": "not_analyzed" + }, + "duration": { + "type": "float" + }, + "orig_bytes": { + "type": "long", + "index": "not_analyzed" + }, + "resp_bytes": { + "type": "long", + "index": "not_analyzed" + }, + "conn_state": { + "type": "string", + "index": "not_analyzed" + }, + "local_orig": { + "type": "boolean" + }, + "local_resp": { + "type": "string", + "index": "not_analyzed" + }, + "missed_bytes": { + "type": "long", + "index": "not_analyzed" + }, + "history": { + "type": "string", + "index": "not_analyzed" + }, + "orig_pkts": { + "type": "long", + "index": "not_analyzed" + }, + "orig_ip_bytes": { + "type": "long", + "index": "not_analyzed" + }, + "resp_pkts": { + "type": "long", + "index": "not_analyzed" + }, + "resp_ip_bytes": { + "type": "long", + "index": "not_analyzed" + }, + "tunnel_parents": { + "type": "string", + "index": "not_analyzed" + }, + /* + * DPD log support + * https://www.bro.org/sphinx-git/scripts/base/frameworks/dpd/main.bro.html#type-DPD::Info + * + * Notable Fields + * Field: proto + * Notes: Field exists in the DNS, Conn, DPD, and Notice logs + */ + "analyzer": { + "type": "string", + "index": "not_analyzed" + }, + "failure_reason": { + "type": "string", + "index": "not_analyzed" + }, + /* + * FTP log support + * https://www.bro.org/sphinx/scripts/base/protocols/ftp/info.bro.html#type-FTP::Info + * + * Notable Fields + * Field: password + * Notes: Field exists in the HTTP and FTP logs + * + * Field: capture_password + * Notes: Field exists in the HTTP and FTP logs + * + * Field: mime_type + * Notes: Field exists in the FTP and Files logs + * + * Field: fuid + * Notes: Field exists in the FTP and Notice logs + */ + "user": { + "type": "string", + "index": "not_analyzed" + }, + "command": { + "type": "string", + "index": "not_analyzed" + }, + "arg": { + "type": "string", + "analyzer": "simple" + }, + "mime_type": { + "type": "string", + "analyzer": "simple" + }, + "file_size": { + "type": "long" + }, + "reply_code": { + "type": "integer" + }, + "reply_msg": { + "type": "string", + "index": "not_analyzed" + }, + "data_channel:passive": { + "type": "boolean" + }, + "data_channel:orig_h": { + "type": "ip" + }, + "data_channel:resp_h": { + "type": "ip" + }, + "data_channel:resp_p": { + "type": "integer" + }, + "cwd": { + "type": "string", + "analyzer": "simple" + }, + "passive": { + "type": "boolean" + }, + "fuid": { + "type": "string", + "index": "not_analyzed" + }, + /* + * Files log support + * https://www.bro.org/sphinx/scripts/base/frameworks/files/main.bro.html#type-Files::Info + * + * Notable Fields + * Field: tx_hosts + * Notes: Metron rewrites this to "ip_src_addr" + * + * Field: rx_hosts + * Notes: Metron rewrites this to "ip_dst_addr" + * + * Field: mime_type + * Notes: Field exists in the FTP and Files logs + */ + "conn_uids": { + "type": "string", + "analyzer": "simple" + }, + "source": { + "type": "string", + "index": "not_analyzed" + }, + "depth": { + "type": "integer" + }, + "analyzers": { + "type": "string", + "analyzer": "simple" + }, + "filename": { + "type": "string", + "index": "not_analyzed" + }, + "is_orig": { + "type": "boolean" + }, + "seen_bytes": { + "type": "long" + }, + "total_bytes": { + "type": "long" + }, + "missing_bytes": { + "type": "long" + }, + "overflow_bytes": { + "type": "long" + }, + "timedout": { + "type": "boolean" + }, + "parent_fuid": { + "type": "string", + "index": "not_analyzed" + }, + "md5": { + "type": "string", + "index": "not_analyzed" + }, + "sha1": { + "type": "string", + "index": "not_analyzed" + }, + "sha256": { + "type": "string", + "index": "not_analyzed" + }, + /* + * Known::CertInfo log support + * https://www.bro.org/sphinx/scripts/policy/protocols/ssl/known-certs.bro.html#type-Known::CertsInfo + * + * Notable Fields + * Field: subject + * Notes: Field exists in the Known::CertInfo and SMTP logs + */ + "port_num": { + "type": "integer" + }, + "subject": { + "type": "string", + "analyzer": "simple" + }, + "issuer_subject": { + "type": "string", + "analyzer": "simple" + }, + "serial": { + "type": "string", + "index": "not_analyzed" + }, + /* + * SMTP log support + * https://www.bro.org/sphinx/scripts/base/protocols/smtp/main.bro.html#type-SMTP::Info + * + * Notable Fields + * Field: subject + * Notes: Field exists in the Known::CertInfo and SMTP logs + */ + "helo": { + "type": "string", + "analyzer": "simple" + }, + "mailfrom": { + "type": "string", + "analyzer": "simple" + }, + "rcptto": { + "type": "string", + "analyzer": "simple" + }, + "date": { + "type": "string", + "index": "not_analyzed" + }, + "from": { + "type": "string", + "analyzer": "simple" + }, + "to": { + "type": "string", + "analyzer": "simple" + }, + "reply_to": { + "type": "string", + "analyzer": "simple" + }, + "msg_id": { + "type": "string", + "index": "not_analyzed" + }, + "in_reply_to": { + "type": "string", + "index": "not_analyzed" + }, + "x_originating_ip": { + "type": "ip" + }, + "first_received": { + "type": "string", + "analyzer": "simple" + }, + "second_received": { + "type": "string", + "analyzer": "simple" + }, + "last_reply": { + "type": "string", + "analyzer": "simple" + }, + "path": { + "type": "string", + "index": "not_analyzed" + }, + "tls": { + "type": "boolean" + }, + "fuids": { + "type": "string", + "index": "not_analyzed" + }, + "is_webmail": { + "type": "boolean" + }, + /* + * SSL log support + * https://www.bro.org/sphinx/scripts/base/protocols/ssl/main.bro.html#type-SSL::Info + * + * Notable Fields + * Field: version + * Notes: Field exists in the HTTP, SSL, and SSH logs + */ + "cipher": { + "type": "string", + "index": "not_analyzed" + }, + "curve": { + "type": "string", + "index": "not_analyzed" + }, + "server_name": { + "type": "string", + "index": "not_analyzed" + }, + "resumed": { + "type": "boolean" + }, + "last_alert": { + "type": "string", + "index": "not_analyzed" + }, + "next_protocol": { + "type": "string", + "index": "not_analyzed" + }, + "established": { + "type": "boolean" + }, + /* + * Weird log support + * https://www.bro.org/sphinx/scripts/base/frameworks/notice/weird.bro.html#type-Weird::Info + */ + "name": { + "type": "string", + "index": "not_analyzed" + }, + "addl": { + "type": "string", + "index": "not_analyzed" + }, + "notice": { + "type": "boolean" + }, + "peer": { + "type": "string", + "index": "not_analyzed" + }, + /* + * Notice log support + * https://www.bro.org/sphinx/scripts/base/frameworks/notice/main.bro.html#type-Notice::Info + * + * Notable Fields + * Field: fuid + * Notes: Field exists in the FTP and Notice logs + * + * Field: proto + * Notes: Field exists in the DNS, Conn, DPD, and Notice logs + */ + "file_mime_type": { + "type": "string", + "index": "not_analyzed" + }, + "file_desc": { + "type": "string", + "index": "not_analyzed" + }, + "note": { + "type": "string", + "index": "not_analyzed" + }, + "msg": { + "type": "string", + "index": "not_analyzed" + }, + "sub": { + "type": "string", + "index": "not_analyzed" + }, + "src": { + "type": "ip" + }, + "dst": { + "type": "ip" + }, + "p": { + "type": "integer", + "index": "not_analyzed" + }, + "n": { + "type": "integer", + "index": "not_analyzed" + }, + "src_peer": { + "type": "ip" + }, + "peer_descr": { + "type": "string", + "index": "not_analyzed" + }, + "actions": { + "type": "string", + "index": "not_analyzed" + }, + "suppress_for": { + "type": "double", + "index": "not_analyzed" + }, + "dropped": { + "type": "boolean" + }, + /* + * DHCP log support + * https://www.bro.org/sphinx/scripts/base/protocols/dhcp/main.bro.html#type-DHCP::Info + * + * Notable Fields + * Field: trans_id + * Notes: Field exists in the DNS and DHCP logs + * + * Field: mac + * Notes: Field exists in the DHCP, RADIUS, and Known::DevicesInfo logs + */ + "mac": { + "type": "string", + "index": "not_analyzed" + }, + "assigned_ip": { + "type": "ip" + }, + "lease_time": { + "type": "float", + "index": "not_analyzed" + }, + /* + * SSH log support + * https://www.bro.org/sphinx/scripts/base/protocols/ssh/main.bro.html#type-SSH::Info + * + * Notable Fields + * Field: version + * Notes: Field exists in the HTTP, SSL, and SSH logs + */ + "auth_success": { + "type": "boolean" + }, + "auth_attempts": { + "type": "integer", + "index": "not_analyzed" + }, + "direction": { + "type": "string", + "index": "not_analyzed" + }, + "client": { + "type": "string", + "index": "not_analyzed" + }, + "server": { + "type": "string", + "index": "not_analyzed" + }, + "cipher_alg": { + "type": "string", + "index": "not_analyzed" + }, + "mac_alg": { + "type": "string", + "index": "not_analyzed" + }, + "compression_alg": { + "type": "string", + "index": "not_analyzed" + }, + "kex_alg": { + "type": "string", + "index": "not_analyzed" + }, + "host_key_alg": { + "type": "string", + "index": "not_analyzed" + }, + "host_key": { + "type": "string", + "index": "not_analyzed" + }, + /* + * Software log support + * https://www.bro.org/sphinx/scripts/base/frameworks/software/main.bro.html#type-Software::Info + * + * Notable Fields + * Field: host + * Notes: Field exists in the HTTP and Software logs + */ + "host_p": { + "type": "integer", + "index": "not_analyzed" + }, + "software_type": { + "type": "string", + "index": "not_analyzed" + }, + "version:major": { + "type": "string", + "index": "not_analyzed" + }, + "version:minor": { + "type": "string", + "index": "not_analyzed" + }, + "version:minor2": { + "type": "string", + "index": "not_analyzed" + }, + "version:minor3": { + "type": "string", + "index": "not_analyzed" + }, + "version:addl": { + "type": "string", + "index": "not_analyzed" + }, + "unparsed_version": { + "type": "string", + "analyzer": "simple" + }, + /* + * RADIUS log support + * https://www.bro.org/sphinx/scripts/base/protocols/radius/main.bro.html#type-RADIUS::Info + * + * Notable Fields + * Field: username + * Notes: Field exists in the HTTP and RADIUS logs + * + * Field: mac + * Notes: Field exists in the DHCP, RADIUS, and Known::DevicesInfo logs + */ + "remote_ip": { + "type": "ip" + }, + "connect_info": { + "type": "string", + "index": "not_analyzed" + }, + "result": { + "type": "string", + "index": "not_analyzed" + }, + /* + * X509 log support + * https://www.bro.org/sphinx/scripts/base/files/x509/main.bro.html#type-X509::Info + * + * Notable Fields + * Field: id + * Notes: In other bro records, the id field is of type conn_id, so it is + * expanded before being logged into 4 fields, all of which are addressed + * under the "Widely-used Bro fields" section of this template. In X509 + * logs, however, id is a string to identify the certificate file id. + */ + "id": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:version": { + "type": "integer", + "index": "not_analyzed" + }, + "certificate:serial": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:subject": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:issuer": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:not_valid_before": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:not_valid_after": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:key_alg": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:sig_alg": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:key_type": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:key_length": { + "type": "integer", + "index": "not_analyzed" + }, + "certificate:exponent": { + "type": "string", + "index": "not_analyzed" + }, + "certificate:curve": { + "type": "string", + "index": "not_analyzed" + }, + "san:dns": { + "type": "string", + "index": "not_analyzed" + }, + "san:uri": { + "type": "string", + "index": "not_analyzed" + }, + "san:email": { + "type": "string", + "index": "not_analyzed" + }, + "san:ip": { + "type": "string", + "index": "not_analyzed" + }, + "basic_constraints:ca": { + "type": "boolean" + }, + "basic_constraints:path_len": { + "type": "integer", + "index": "not_analyzed" + }, + /* + * Known::DevicesInfo log support + * https://www.bro.org/sphinx/scripts/policy/misc/known-devices.bro.html#type-Known::DevicesInfo + * + * Notable Fields + * Field: mac + * Notes: Field exists in the DHCP, RADIUS, and Known::DevicesInfo logs + */ + "dhcp_host_name": { + "type": "string", + "index": "not_analyzed" + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/e2e/mock-data/setup.sh ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/mock-data/setup.sh b/metron-interface/metron-alerts/e2e/mock-data/setup.sh new file mode 100755 index 0000000..cdaacb2 --- /dev/null +++ b/metron-interface/metron-alerts/e2e/mock-data/setup.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# 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. +# +curl -s -XPOST http://node1:9200/_template/alerts_ui_e2e_index -d @alerts_ui_e2e_index.template +curl -s -XPOST http://node1:9200/alerts_ui_e2e_index/alerts_ui_e2e_doc/_bulk --data-binary @alerts_ui_e2e_index.data http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/e2e/mock-data/teardown.sh ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/mock-data/teardown.sh b/metron-interface/metron-alerts/e2e/mock-data/teardown.sh new file mode 100755 index 0000000..be2e365 --- /dev/null +++ b/metron-interface/metron-alerts/e2e/mock-data/teardown.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# 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. +# +curl -s -XDELETE "http://node1:9200/alerts_ui_e2e_index" http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/e2e/utils/e2e_util.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/e2e/utils/e2e_util.ts b/metron-interface/metron-alerts/e2e/utils/e2e_util.ts index 836818e..ce5609a 100644 --- a/metron-interface/metron-alerts/e2e/utils/e2e_util.ts +++ b/metron-interface/metron-alerts/e2e/utils/e2e_util.ts @@ -1,4 +1,6 @@ import { browser, protractor } from 'protractor'; +import request = require('request'); +import fs = require('fs'); export function changeURL(url: string) { return browser.get(url).then(() => { @@ -28,3 +30,12 @@ export function waitForStalenessOf (_element ) { return browser.wait(EC.stalenessOf(_element)); } +export function loadTestData() { + deleteTestData(); + fs.createReadStream('e2e/mock-data/alerts_ui_e2e_index.template').pipe(request.post('http://node1:9200/_template/alerts_ui_e2e_index')); + fs.createReadStream('e2e/mock-data/alerts_ui_e2e_index.data').pipe(request.post('http://node1:9200/alerts_ui_e2e_index/alerts_ui_e2e_doc/_bulk')); +} + +export function deleteTestData() { + request.delete('http://node1:9200/alerts_ui_e2e_index*'); +} http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/protractor.conf.js ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/protractor.conf.js b/metron-interface/metron-alerts/protractor.conf.js index 189195c..6a82e9c 100644 --- a/metron-interface/metron-alerts/protractor.conf.js +++ b/metron-interface/metron-alerts/protractor.conf.js @@ -26,9 +26,11 @@ exports.config = { allScriptsTimeout: 25000, specs: [ './e2e/login/login.e2e-spec.ts', - '/e2e/alerts-list/alerts-list.e2e-spec.ts', + './e2e/alerts-list/alerts-list.e2e-spec.ts', './e2e/alerts-list/configure-table/configure-table.e2e-spec.ts', - './e2e/alerts-list/save-search/save-search.e2e-spec.ts' + './e2e/alerts-list/save-search/save-search.e2e-spec.ts', + './e2e/alerts-list/alert-status/alerts-list-status.e2e-spec.ts', + './e2e/alert-details/alert-status/alert-details-status.e2e-spec.ts' ], capabilities: { 'browserName': 'chrome', http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh b/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh index 7516fd0..36a239c 100755 --- a/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh +++ b/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh @@ -16,6 +16,4 @@ # limitations under the License. # SCRIPTS_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd $SCRIPTS_ROOT/.. && npm run build -node $SCRIPTS_ROOT/../alerts-server-e2e.js -p 4200 -r http://node1:8082 - +$SCRIPTS_ROOT/../node_modules/@angular/cli/bin/ng serve -environment e2e --proxy-config proxy.conf.json $@ http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html index 703b676..8c82fab 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html +++ b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html @@ -23,17 +23,17 @@ <table> <tr> <td class="title"> Status</td> - <td class="secondary" [ngClass]="{'primary': selectedAlertState === alertState.ESCALATE, 'secondary': selectedAlertState !== alertState.ESCALATE}" (click)="processEscalate()">ESCALATE</td> + <td [ngClass]="{'primary': selectedAlertState === alertState.ESCALATE, 'secondary': selectedAlertState !== alertState.ESCALATE}" (click)="processEscalate()">ESCALATE</td> <td></td> </tr> <tr> - <td class="secondary" [ngClass]="{'primary': selectedAlertState === alertState.NEW, 'secondary': selectedAlertState !== alertState.NEW}" (click)="processNew()">NEW</td> - <td class="primary" [ngClass]="{'primary': selectedAlertState === alertState.OPEN, 'secondary': selectedAlertState !== alertState.OPEN}" (click)="processOpen()">OPEN</td> - <td class="secondary" [ngClass]="{'primary': selectedAlertState === alertState.DISMISS, 'secondary': selectedAlertState !== alertState.DISMISS}" (click)="processDismiss()">DISMISS</td> + <td [ngClass]="{'primary': selectedAlertState === alertState.NEW, 'secondary': selectedAlertState !== alertState.NEW}" (click)="processNew()">NEW</td> + <td [ngClass]="{'primary': selectedAlertState === alertState.OPEN, 'secondary': selectedAlertState !== alertState.OPEN}" (click)="processOpen()">OPEN</td> + <td [ngClass]="{'primary': selectedAlertState === alertState.DISMISS, 'secondary': selectedAlertState !== alertState.DISMISS}" (click)="processDismiss()">DISMISS</td> </tr> <tr> <td></td> - <td class="secondary" [ngClass]="{'primary': selectedAlertState === alertState.RESOLVE, 'secondary': selectedAlertState !== alertState.RESOLVE}" (click)="processResolve()">RESOLVE</td> + <td [ngClass]="{'primary': selectedAlertState === alertState.RESOLVE, 'secondary': selectedAlertState !== alertState.RESOLVE}" (click)="processResolve()">RESOLVE</td> <td></td> </tr> </table> http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts index 2e7884e..2efb2ce 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts @@ -18,8 +18,9 @@ import { Component, OnInit } from '@angular/core'; import {Router, ActivatedRoute} from '@angular/router'; import {SearchService} from '../../service/search.service'; +import {UpdateService} from '../../service/update.service'; import {Alert} from '../../model/alert'; -import {WorkflowService} from '../../service/workflow.service'; +import {AlertsService} from '../../service/alerts.service'; import {AlertSource} from '../../model/alert-source'; export enum AlertState { @@ -43,7 +44,8 @@ export class AlertDetailsComponent implements OnInit { constructor(private router: Router, private activatedRoute: ActivatedRoute, private searchService: SearchService, - private workflowService: WorkflowService) { } + private updateService: UpdateService, + private alertsService: AlertsService) { } goBack() { this.router.navigateByUrl('/alerts-list'); @@ -54,9 +56,24 @@ export class AlertDetailsComponent implements OnInit { this.searchService.getAlert(this.alertSourceType, this.alertId).subscribe(alert => { this.alertSource = alert; this.alertFields = Object.keys(alert).filter(field => !field.includes(':ts') && field !== 'original_string').sort(); + this.selectedAlertState = this.getAlertState(alert['alert_status']); }); } + getAlertState(alertStatus) { + if (alertStatus === 'OPEN') { + return AlertState.OPEN; + } else if (alertStatus === 'ESCALATE') { + return AlertState.ESCALATE; + } else if (alertStatus === 'DISMISS') { + return AlertState.DISMISS; + } else if (alertStatus === 'RESOLVE') { + return AlertState.RESOLVE; + } else { + return AlertState.NEW; + } + } + ngOnInit() { this.activatedRoute.params.subscribe(params => { this.alertId = params['guid']; @@ -70,7 +87,7 @@ export class AlertDetailsComponent implements OnInit { tAlert.source = this.alertSource; this.selectedAlertState = AlertState.OPEN; - this.searchService.updateAlertState([tAlert], 'OPEN', '').subscribe(results => { + this.updateService.updateAlertState([tAlert], 'OPEN').subscribe(results => { this.getData(); }); } @@ -80,7 +97,7 @@ export class AlertDetailsComponent implements OnInit { tAlert.source = this.alertSource; this.selectedAlertState = AlertState.NEW; - this.searchService.updateAlertState([tAlert], 'NEW', '').subscribe(results => { + this.updateService.updateAlertState([tAlert], 'NEW').subscribe(results => { this.getData(); }); } @@ -90,11 +107,10 @@ export class AlertDetailsComponent implements OnInit { tAlert.source = this.alertSource; this.selectedAlertState = AlertState.ESCALATE; - this.workflowService.start([tAlert]).subscribe(workflowId => { - this.searchService.updateAlertState([tAlert], 'ESCALATE', workflowId).subscribe(results => { - this.getData(); - }); + this.updateService.updateAlertState([tAlert], 'ESCALATE').subscribe(results => { + this.getData(); }); + this.alertsService.escalate([tAlert]).subscribe(); } processDismiss() { @@ -102,7 +118,7 @@ export class AlertDetailsComponent implements OnInit { tAlert.source = this.alertSource; this.selectedAlertState = AlertState.DISMISS; - this.searchService.updateAlertState([tAlert], 'DISMISS', '').subscribe(results => { + this.updateService.updateAlertState([tAlert], 'DISMISS').subscribe(results => { this.getData(); }); } @@ -112,7 +128,7 @@ export class AlertDetailsComponent implements OnInit { tAlert.source = this.alertSource; this.selectedAlertState = AlertState.RESOLVE; - this.searchService.updateAlertState([tAlert], 'RESOLVE', '').subscribe(results => { + this.updateService.updateAlertState([tAlert], 'RESOLVE').subscribe(results => { this.getData(); }); } http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.module.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.module.ts b/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.module.ts index e7dd735..9b4927e 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.module.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.module.ts @@ -19,11 +19,12 @@ import { NgModule } from '@angular/core'; import {routing} from './alerts-details.routing'; import {SharedModule} from '../../shared/shared.module'; import {AlertDetailsComponent} from './alert-details.component'; -import {WorkflowService} from '../../service/workflow.service'; +import {AlertsService} from '../../service/alerts.service'; +import {UpdateService} from '../../service/update.service'; @NgModule ({ imports: [ routing, SharedModule], declarations: [ AlertDetailsComponent ], - providers: [ WorkflowService ], + providers: [ AlertsService, UpdateService ], }) export class AlertDetailsModule { } http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html index c31b9f8..856a3a3 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html @@ -66,13 +66,17 @@ <div class="row"> <div class="col-sm-12 pl-0"> <app-table-view #dataViewComponent + [alerts]="alerts" [queryBuilder]="queryBuilder" + [pagination]="pagination" [alertsColumnsToDisplay]="alertsColumnsToDisplay" [(selectedAlerts)]="selectedAlerts" (onResize)="onResize()" (onAddFilter)="onAddFilter($event)" + (onRefreshData)="onRefreshData($event)" (onShowDetails)="showDetails($event)" - (onShowConfigureTable)="showConfigureTable()"></app-table-view> + (onShowConfigureTable)="showConfigureTable()" + (onSelectedAlertsChange)="onSelectedAlertsChange($event)"></app-table-view> </div> </div> </div> http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts index ae86002..039ed48 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts @@ -21,9 +21,10 @@ import {Observable, Subscription} from 'rxjs/Rx'; import {Alert} from '../../model/alert'; import {SearchService} from '../../service/search.service'; +import {UpdateService} from '../../service/update.service'; import {QueryBuilder} from './query-builder'; import {ConfigureTableService} from '../../service/configure-table.service'; -import {WorkflowService} from '../../service/workflow.service'; +import {AlertsService} from '../../service/alerts.service'; import {ClusterMetaDataService} from '../../service/cluster-metadata.service'; import {ColumnMetadata} from '../../model/column-metadata'; import {SaveSearchService} from '../../service/save-search.service'; @@ -36,6 +37,8 @@ import {SearchResponse} from '../../model/search-response'; import {ElasticsearchUtils} from '../../utils/elasticsearch-utils'; import {TableViewComponent} from './table-view/table-view.component'; import {Filter} from '../../model/filter'; +import {Pagination} from '../../model/pagination'; +import {environment} from '../../../environments/environment'; @Component({ selector: 'app-alerts-list', @@ -52,10 +55,11 @@ export class AlertsListComponent implements OnInit, OnDestroy { searchResponse: SearchResponse = new SearchResponse(); colNumberTimerId: number; refreshInterval = RefreshInterval.ONE_MIN; + refreshTimer: Subscription; pauseRefresh = false; lastPauseRefreshValue = false; threatScoreFieldName = 'threat:triage:score'; - refreshTimer: Subscription; + indices: string[]; @ViewChild('table') table: ElementRef; @ViewChild('dataViewComponent') dataViewComponent: TableViewComponent; @@ -63,11 +67,13 @@ export class AlertsListComponent implements OnInit, OnDestroy { tableMetaData = new TableMetadata(); queryBuilder: QueryBuilder = new QueryBuilder(); + pagination: Pagination = new Pagination(); constructor(private router: Router, private searchService: SearchService, + private updateService: UpdateService, private configureTableService: ConfigureTableService, - private workflowService: WorkflowService, + private alertsService: AlertsService, private clusterMetaDataService: ClusterMetaDataService, private saveSearchService: SaveSearchService, private metronDialogBox: MetronDialogBox, @@ -78,6 +84,9 @@ export class AlertsListComponent implements OnInit, OnDestroy { this.restoreRefreshState(); } }); + if (environment.indices) { + this.indices = environment.indices.split(','); + } } addAlertColChangedListner() { @@ -155,6 +164,18 @@ export class AlertsListComponent implements OnInit, OnDestroy { return false; } + onRefreshData($event) { + this.search($event); + } + + onSelectedAlertsChange(selectedAlerts) { + if (selectedAlerts.length > 0) { + this.pause(); + } else { + this.resume(); + } + } + onAddFilter(filter: Filter) { this.queryBuilder.addOrUpdateFilter(filter); this.search(); @@ -165,11 +186,6 @@ export class AlertsListComponent implements OnInit, OnDestroy { this.search(); } - searchView(resetPaginationParams = true, pageSize: number = null) { - this.changeDetector.detectChanges(); - this.dataViewComponent.search(resetPaginationParams, pageSize); - } - onPausePlay() { this.pauseRefresh = !this.pauseRefresh; if (this.pauseRefresh) { @@ -201,27 +217,27 @@ export class AlertsListComponent implements OnInit, OnDestroy { } processEscalate() { - this.workflowService.start(this.selectedAlerts).subscribe(workflowId => { - this.searchService.updateAlertState(this.selectedAlerts, 'ESCALATE', workflowId).subscribe(results => { - this.updateSelectedAlertStatus('ESCALATE'); - }); + this.updateService.updateAlertState(this.selectedAlerts, 'ESCALATE').subscribe(results => { + this.updateSelectedAlertStatus('ESCALATE'); }); + this.alertsService.escalate(this.selectedAlerts).subscribe(); + } processDismiss() { - this.searchService.updateAlertState(this.selectedAlerts, 'DISMISS', '').subscribe(results => { + this.updateService.updateAlertState(this.selectedAlerts, 'DISMISS').subscribe(results => { this.updateSelectedAlertStatus('DISMISS'); }); } processOpen() { - this.searchService.updateAlertState(this.selectedAlerts, 'OPEN', '').subscribe(results => { + this.updateService.updateAlertState(this.selectedAlerts, 'OPEN').subscribe(results => { this.updateSelectedAlertStatus('OPEN'); }); } processResolve() { - this.searchService.updateAlertState(this.selectedAlerts, 'RESOLVE', '').subscribe(results => { + this.updateService.updateAlertState(this.selectedAlerts, 'RESOLVE').subscribe(results => { this.updateSelectedAlertStatus('RESOLVE'); }); } @@ -237,11 +253,18 @@ export class AlertsListComponent implements OnInit, OnDestroy { } search(resetPaginationParams = true, savedSearch?: SaveSearch) { - this.selectedAlerts = []; - this.saveCurrentSearch(savedSearch); - - this.queryBuilder.setFromAndSize(0, 0); + if (resetPaginationParams) { + this.pagination.from = 0; + } + this.queryBuilder.searchRequest.from = this.pagination.from; + if (this.tableMetaData.size) { + this.pagination.size = this.tableMetaData.size; + } + this.queryBuilder.searchRequest.size = this.pagination.size; + if (this.indices) { + this.queryBuilder.searchRequest.indices = this.indices; + } this.searchService.search(this.queryBuilder.searchRequest).subscribe(results => { this.setData(results); }, error => { @@ -249,8 +272,6 @@ export class AlertsListComponent implements OnInit, OnDestroy { this.metronDialogBox.showConfirmationMessage(ElasticsearchUtils.extractESErrorMessage(error), DialogType.Error); }); - this.searchView(resetPaginationParams, this.tableMetaData.size); - this.tryStartPolling(); } @@ -269,7 +290,9 @@ export class AlertsListComponent implements OnInit, OnDestroy { } setData(results: SearchResponse) { + this.selectedAlerts = []; this.searchResponse = results; + this.pagination.total = results.total; this.alerts = results.results ? results.results : []; } @@ -290,6 +313,15 @@ export class AlertsListComponent implements OnInit, OnDestroy { this.tryStopPolling(); } + pause() { + this.pauseRefresh = true; + this.tryStopPolling(); + } + + resume() { + this.pauseRefresh = false; + this.tryStartPolling(); + } showSavedSearches() { this.saveRefreshState(); @@ -307,7 +339,6 @@ export class AlertsListComponent implements OnInit, OnDestroy { this.tryStopPolling(); this.refreshTimer = this.searchService.pollSearch(this.queryBuilder.searchRequest).subscribe(results => { this.setData(results); - this.searchView(false); }); } } @@ -323,8 +354,13 @@ export class AlertsListComponent implements OnInit, OnDestroy { } updateSelectedAlertStatus(status: string) { - for (let alert of this.selectedAlerts) { - alert.status = status; + for (let selectedAlert of this.selectedAlerts) { + selectedAlert.status = status; + this.alerts.filter(alert => alert.source.guid == selectedAlert.source.guid) + .map(alert => alert.source['alert_status'] = status); } + this.selectedAlerts = []; + this.resume(); } + } http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts index c1025f0..805265c 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts @@ -21,6 +21,7 @@ import {AlertsListComponent} from './alerts-list.component'; import {routing} from './alerts-list.routing'; import {SharedModule} from '../../shared/shared.module'; import {SearchService} from '../../service/search.service'; +import {UpdateService} from '../../service/update.service'; import {MetronSorterModule} from '../../shared/metron-table/metron-sorter/metron-sorter.module'; import {ListGroupModule} from '../../shared/list-group/list-grup.module'; import {CollapseModule} from '../../shared/collapse/collapse.module'; @@ -33,7 +34,7 @@ import {TableViewComponent} from './table-view/table-view.component'; ListGroupModule, CollapseModule], exports: [AlertsListComponent], declarations: [AlertsListComponent, TableViewComponent], - providers: [SearchService] + providers: [SearchService, UpdateService] }) export class AlertsListModule { } http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.html ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.html b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.html index 8fd0077..ae788fc 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.html +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.html @@ -37,6 +37,6 @@ </div> <div clas="row"> <div class="col-md-3 push-md-5"> - <metron-table-pagination [(pagingData)]="pagingData" (pageChange)="onPageChange()"> </metron-table-pagination> + <metron-table-pagination [(pagination)]="pagination" (pageChange)="onPageChange()"> </metron-table-pagination> </div> </div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts index 49f969f..fa2f97e 100644 --- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts +++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/table-view/table-view.component.ts @@ -23,10 +23,8 @@ import {Pagination} from '../../../model/pagination'; import {SortEvent} from '../../../shared/metron-table/metron-table.directive'; import {ColumnMetadata} from '../../../model/column-metadata'; import {Alert} from '../../../model/alert'; -import {SearchResponse} from '../../../model/search-response'; import {SearchService} from '../../../service/search.service'; -import {MetronDialogBox, DialogType} from '../../../shared/metron-dialog-box'; -import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils'; +import {MetronDialogBox} from '../../../shared/metron-dialog-box'; import {QueryBuilder} from '../query-builder'; import {Sort} from '../../../utils/enums'; import {Filter} from '../../../model/filter'; @@ -39,24 +37,25 @@ import {Filter} from '../../../model/filter'; export class TableViewComponent { - alerts: Alert[] = []; + threatScoreFieldName = 'threat:triage:score'; router: Router; searchService: SearchService; metronDialogBox: MetronDialogBox; - pagingData = new Pagination(); - searchResponse: SearchResponse = new SearchResponse(); + @Input() alerts: Alert[] = []; @Input() queryBuilder: QueryBuilder; + @Input() pagination: Pagination; @Input() alertsColumnsToDisplay: ColumnMetadata[] = []; @Input() selectedAlerts: Alert[] = []; - + @Output() onResize = new EventEmitter<void>(); @Output() onAddFilter = new EventEmitter<Filter>(); + @Output() onRefreshData = new EventEmitter<boolean>(); @Output() onShowDetails = new EventEmitter<Alert>(); @Output() onShowConfigureTable = new EventEmitter<Alert>(); - @Output() selectedAlertsChange = new EventEmitter< Alert[]>(); + @Output() onSelectedAlertsChange = new EventEmitter< Alert[]>(); constructor(router: Router, searchService: SearchService, @@ -66,33 +65,11 @@ export class TableViewComponent { this.metronDialogBox = metronDialogBox; } - search(resetPaginationParams = true, pageSize: number = null) { - if (resetPaginationParams) { - this.pagingData.from = 0; - } - - this.pagingData.size = pageSize === null ? this.pagingData.size : pageSize; - this.queryBuilder.setFromAndSize(this.pagingData.from, this.pagingData.size); - - this.searchService.search(this.queryBuilder.searchRequest).subscribe(results => { - this.setAlertData(results); - }, error => { - this.setAlertData(new SearchResponse()); - this.metronDialogBox.showConfirmationMessage(ElasticsearchUtils.extractESErrorMessage(error), DialogType.Error); - }); - } - - setAlertData(results: SearchResponse) { - this.searchResponse = results; - this.pagingData.total = results.total; - this.alerts = this.searchResponse.results ? this.searchResponse.results : []; - } - onSort(sortEvent: SortEvent) { let sortOrder = (sortEvent.sortOrder === Sort.ASC ? 'asc' : 'desc'); let sortBy = sortEvent.sortBy === 'id' ? '_uid' : sortEvent.sortBy; this.queryBuilder.setSort(sortBy, sortOrder); - this.search(); + this.onRefreshData.emit(true); } getValue(alert: Alert, column: ColumnMetadata, formatData: boolean) { @@ -103,7 +80,8 @@ export class TableViewComponent { returnValue = alert[column.name]; break; case 'alert_status': - returnValue = 'NEW'; + let alertStatus = alert.source['alert_status']; + returnValue = alertStatus ? alertStatus : 'NEW'; break; default: returnValue = alert.source[column.name]; @@ -129,7 +107,8 @@ export class TableViewComponent { } onPageChange() { - this.search(false); + this.queryBuilder.setFromAndSize(this.pagination.from, this.pagination.size); + this.onRefreshData.emit(false); } selectRow($event, alert: Alert) { @@ -139,7 +118,7 @@ export class TableViewComponent { this.selectedAlerts.splice(this.selectedAlerts.indexOf(alert), 1); } - this.selectedAlertsChange.emit(this.selectedAlerts); + this.onSelectedAlertsChange.emit(this.selectedAlerts); } selectAllRows($event) { @@ -148,7 +127,7 @@ export class TableViewComponent { this.selectedAlerts = this.alerts; } - this.selectedAlertsChange.emit(this.selectedAlerts); + this.onSelectedAlertsChange.emit(this.selectedAlerts); } resize() { http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/model/patch-request.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/model/patch-request.ts b/metron-interface/metron-alerts/src/app/model/patch-request.ts new file mode 100644 index 0000000..8e984ab --- /dev/null +++ b/metron-interface/metron-alerts/src/app/model/patch-request.ts @@ -0,0 +1,24 @@ +/** + * 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. + */ +export class PatchRequest { + guid: string; + sensorType: string; + index: string; + patch: {}; + source: {}; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/service/alerts.service.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/service/alerts.service.ts b/metron-interface/metron-alerts/src/app/service/alerts.service.ts new file mode 100644 index 0000000..7324a72 --- /dev/null +++ b/metron-interface/metron-alerts/src/app/service/alerts.service.ts @@ -0,0 +1,36 @@ +/** + * 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 {Injectable} from '@angular/core'; +import {Observable} from 'rxjs/Rx'; +import {Alert} from '../model/alert'; +import {Http, Headers, RequestOptions} from '@angular/http'; +import {HttpUtil} from '../utils/httpUtil'; + +@Injectable() +export class AlertsService { + + defaultHeaders = {'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest'}; + + constructor(private http: Http) { + } + + public escalate(alerts: Alert[]): Observable<null> { + return this.http.post('/api/v1/alert/escalate', alerts, new RequestOptions({headers: new Headers(this.defaultHeaders)})) + .catch(HttpUtil.handleError); + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/service/data-source.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/service/data-source.ts b/metron-interface/metron-alerts/src/app/service/data-source.ts index f4f90ed..f6d6cc0 100644 --- a/metron-interface/metron-alerts/src/app/service/data-source.ts +++ b/metron-interface/metron-alerts/src/app/service/data-source.ts @@ -22,9 +22,6 @@ import {ColumnMetadata} from '../model/column-metadata'; import {ColumnNames} from '../model/column-names'; import {TableMetadata} from '../model/table-metadata'; import {SaveSearch} from '../model/save-search'; -import {SearchResponse} from '../model/search-response'; -import {SearchRequest} from '../model/search-request'; -import {AlertSource} from '../model/alert-source'; @Injectable() export abstract class DataSource { @@ -32,14 +29,8 @@ export abstract class DataSource { constructor(protected http: Http) {} - // Calls to fetch alerts - abstract getAlerts(searchRequest: SearchRequest): Observable<SearchResponse> - abstract getAlert(sourceType: string, alertId: string): Observable<AlertSource> - abstract updateAlertState(request: any): Observable<{}> - // Calls to fetch default alert table column names and all the field names across all indexes abstract getDefaultAlertTableColumnNames(): Observable<ColumnMetadata[]> - abstract getAllFieldNames(): Observable<ColumnMetadata[]> // Calls to rename field names and to fetch the renamed field names abstract getAlertTableColumnNames(): Observable<ColumnNames[]> http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/service/search.service.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/service/search.service.ts b/metron-interface/metron-alerts/src/app/service/search.service.ts index be3b1f6..d8842b8 100644 --- a/metron-interface/metron-alerts/src/app/service/search.service.ts +++ b/metron-interface/metron-alerts/src/app/service/search.service.ts @@ -23,9 +23,7 @@ import 'rxjs/add/operator/switchMap'; import 'rxjs/add/operator/onErrorResumeNext'; import {HttpUtil} from '../utils/httpUtil'; -import {Alert} from '../model/alert'; import {Http} from '@angular/http'; -import {DataSource} from './data-source'; import {SearchResponse} from '../model/search-response'; import {SearchRequest} from '../model/search-request'; import {AlertSource} from '../model/alert-source'; @@ -57,7 +55,6 @@ export class SearchService { } constructor(private http: Http, - private dataSource: DataSource, private ngZone: NgZone) { } public getAlert(sourceType: string, alertId: string): Observable<AlertSource> { @@ -95,18 +92,4 @@ export class SearchService { .catch(HttpUtil.handleError) .onErrorResumeNext(); } - - public updateAlertState(alerts: Alert[], state: string, workflowId: string) { - let request = ''; - for (let alert of alerts) { - request += '{ "update" : { "sensorType" : "' + alert.source['source:type'] + '", "guid" : "' + alert.source.guid + '" } }\n' + - '{ "doc": { "alert_status": "' + state + '"'; - if (workflowId) { - request += ', "workflow_id": "' + workflowId + '"'; - } - request += ' }}\n'; - } - - return this.dataSource.updateAlertState(request); - } } http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/service/update.service.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/service/update.service.ts b/metron-interface/metron-alerts/src/app/service/update.service.ts new file mode 100644 index 0000000..c4bc7d6 --- /dev/null +++ b/metron-interface/metron-alerts/src/app/service/update.service.ts @@ -0,0 +1,58 @@ +/** + * 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 {Injectable} from '@angular/core'; +import {Headers, RequestOptions} from '@angular/http'; +import {Observable} from 'rxjs/Rx'; +import 'rxjs/add/observable/interval'; +import 'rxjs/add/operator/switchMap'; +import 'rxjs/add/operator/onErrorResumeNext'; + +import {HttpUtil} from '../utils/httpUtil'; +import {Alert} from '../model/alert'; +import {Http} from '@angular/http'; +import {PatchRequest} from '../model/patch-request'; + +@Injectable() +export class UpdateService { + + defaultHeaders = {'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest'}; + + + constructor(private http: Http) { } + + public patch(patchRequest: PatchRequest): Observable<{}> { + let url = '/api/v1/update/patch'; + return this.http.patch(url, patchRequest, new RequestOptions({headers: new Headers(this.defaultHeaders)})) + .catch(HttpUtil.handleError); + } + + public updateAlertState(alerts: Alert[], state: string): Observable<{}> { + let patchRequests: PatchRequest[] = alerts.map(alert => { + let patchRequest = new PatchRequest(); + patchRequest.guid = alert.source.guid; + patchRequest.sensorType = alert.source['source:type']; + patchRequest.patch = [{'op': 'add', 'path': '/alert_status', 'value': state}]; + return patchRequest; + }); + let patchObservables = []; + for (let patchRequest of patchRequests) { + patchObservables.push(this.patch(patchRequest)); + } + return Observable.forkJoin(patchObservables); + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/service/workflow.service.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/service/workflow.service.ts b/metron-interface/metron-alerts/src/app/service/workflow.service.ts deleted file mode 100644 index 060769f..0000000 --- a/metron-interface/metron-alerts/src/app/service/workflow.service.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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 {Injectable} from '@angular/core'; -import {Observable} from 'rxjs/Rx'; -import {Alert} from '../model/alert'; -import {Http, Headers, RequestOptions} from '@angular/http'; -import {HttpUtil} from '../utils/httpUtil'; - -@Injectable() -export class WorkflowService { - - defaultHeaders = {'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest'}; - - constructor(private http: Http) { - } - - public start(alerts: Alert[]): Observable<string> { - return this.http.post('/api/v1/workflow', alerts, new RequestOptions({headers: new Headers(this.defaultHeaders)})) - .map(HttpUtil.extractString); - } -} http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts index 0aaa217..b61ac03 100644 --- a/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts +++ b/metron-interface/metron-alerts/src/app/shared/metron-table/metron-table-pagination/metron-table-pagination.component.ts @@ -25,17 +25,8 @@ import {Pagination} from '../../../model/pagination'; }) export class MetronTablePaginationComponent { + @Input() pagination = new Pagination(); @Output() pageChange = new EventEmitter(); - pagination = new Pagination(); - - @Input() - get pagingData() { - return this.pagination; - } - - set pagingData(val) { - this.pagination = val; - } onPrevious() { this.pagination.from -= this.pagination.size; http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/environments/environment.e2e.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/environments/environment.e2e.ts b/metron-interface/metron-alerts/src/environments/environment.e2e.ts new file mode 100644 index 0000000..4a11048 --- /dev/null +++ b/metron-interface/metron-alerts/src/environments/environment.e2e.ts @@ -0,0 +1,21 @@ +/** + * 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. + */ +export const environment = { + production: false, + indices: 'alerts_ui_e2e' +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/environments/environment.prod.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/environments/environment.prod.ts b/metron-interface/metron-alerts/src/environments/environment.prod.ts index 1b628e3..04e62a9 100644 --- a/metron-interface/metron-alerts/src/environments/environment.prod.ts +++ b/metron-interface/metron-alerts/src/environments/environment.prod.ts @@ -16,5 +16,6 @@ * limitations under the License. */ export const environment = { - production: true + production: true, + indices: null }; http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-alerts/src/environments/environment.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/environments/environment.ts b/metron-interface/metron-alerts/src/environments/environment.ts index 041db37..91fdbaf 100644 --- a/metron-interface/metron-alerts/src/environments/environment.ts +++ b/metron-interface/metron-alerts/src/environments/environment.ts @@ -21,5 +21,6 @@ // The list of which env maps to which file can be found in `angular-cli.json`. export const environment = { - production: false + production: false, + indices: null }; http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/metron-interface/metron-config/package.json ---------------------------------------------------------------------- diff --git a/metron-interface/metron-config/package.json b/metron-interface/metron-config/package.json index 08d375b..1c384f8 100644 --- a/metron-interface/metron-config/package.json +++ b/metron-interface/metron-config/package.json @@ -60,6 +60,7 @@ "protractor": "4.0.5", "ts-node": "1.2.1", "tslint": "3.13.0", - "typescript": "~2.0.3" + "typescript": "~2.0.3", + "@types/request": "2.0.3" } } http://git-wip-us.apache.org/repos/asf/metron/blob/cd7257e1/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 3f0af7e..b22a2c9 100644 --- a/pom.xml +++ b/pom.xml @@ -353,6 +353,8 @@ <!-- Checkstyle is LGPL. We derive ours from their base, but don't ship it, so it's fine use. Since it is derived, we shouldn't get an Apache header --> <exclude>checkstyle.xml</exclude> + <!-- Alerts UI e2e test data --> + <exclude>e2e/mock-data/alerts_ui_e2e_index.data</exclude> </excludes> </configuration> </plugin>
