logstash-input-sdee 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +12 -0
- data/CONTRIBUTORS +10 -0
- data/Gemfile +2 -0
- data/LICENSE +13 -0
- data/README.md +190 -0
- data/examples/patterns/cisco +79 -0
- data/examples/sdee.conf +35 -0
- data/lib/logstash/inputs/sdee.rb +354 -0
- data/logstash-input-sdee.gemspec +21 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2e5c47c9f0d817a1e1d1fbb697e896ffc7fe0ef4
|
4
|
+
data.tar.gz: 6df5bb5d6942b4554216a032379a4ecf00989573
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5ef8b0e84db55e36509d00af50cd6134b642ee4ee051c3a07f102cdf86af3dd74fcc217d5877e5451e6251b76a8e1ccb41d14135860955bd7c7fab174540f082
|
7
|
+
data.tar.gz: de12fddd14935ebd9b8e377cd64b605f544ec5b9f8dc354999d7414b1496e8c4a9f76c8116db1a00691723a6866629146d3b3b31c43a04c39e5b37665794488d
|
data/CHANGELOG.md
ADDED
data/CONTRIBUTORS
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
The following is a list of people who have contributed ideas, code, bug
|
2
|
+
reports, or in general have helped logstash-input-sdee along its way.
|
3
|
+
|
4
|
+
Contributors:
|
5
|
+
* Me (roootik@gmail.com)
|
6
|
+
|
7
|
+
Note: If you've sent me patches, bug reports, or otherwise contributed to
|
8
|
+
logstash, and you aren't on the list above and want to be, please let me know
|
9
|
+
and I'll make sure you're here. Contributions from folks like you are what make
|
10
|
+
open source awesome.
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2014–2016 rootik <roootik@gmail.com>
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# Logstash Cisco SDEE/CIDEE input plugin
|
2
|
+
|
3
|
+
This plugin is based off [logstash-input-http_poller](https://github.com/logstash-plugins/logstash-input-http_poller) by @maximede.
|
4
|
+
|
5
|
+
This [Logstash](https://github.com/elasticsearch/logstash) input plugin allows you to call a Cisco SDEE/CIDEE HTTP API, decode the output of it into event(s), and send them on their merry way.
|
6
|
+
|
7
|
+
The idea behind this plugins came from a need to gather events from Cisco security devices and feed them to ELK stack.
|
8
|
+
|
9
|
+
This plugin is tested on:
|
10
|
+
* Hardware: Cisco ASA 5585-X IPS SSP-10
|
11
|
+
* IPS Version: 7.3(2)E4
|
12
|
+
* logstash 2.0.0-beta1
|
13
|
+
* Java JRE 1.8.0-60
|
14
|
+
|
15
|
+
It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
|
16
|
+
|
17
|
+
## TODO
|
18
|
+
- Add request options like minThreatRating and maxThreatRating, virtualSensors, errorSeverities, includeStatusCategories, excludeStatusCategories and so on.
|
19
|
+
- Gather sensor status and health events
|
20
|
+
|
21
|
+
## Config Example
|
22
|
+
|
23
|
+
For config examples see `sdee.conf` in `examples` in this repo.
|
24
|
+
|
25
|
+
## SSL notes
|
26
|
+
|
27
|
+
You need to import host SSL certificate in Java trust store to be able to connect to Cisco IPS device.
|
28
|
+
I have had no luck with `truststore` nor `ssl_certificate_validation` configuration options with Java 1.8.0-60 like mentioned in [logstash-mixin-http_client](https://github.com/logstash-plugins/logstash-mixin-http_client) documentation,
|
29
|
+
so I'm using system trustStore - `$JAVA_HOME/lib/security/cacerts`. Note, default Java trustStore password is `changeit`.
|
30
|
+
Take the following steps:
|
31
|
+
|
32
|
+
* Get server certificate from IPS device:
|
33
|
+
```sh
|
34
|
+
echo | openssl s_client -connect ciscoips:443 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
|
35
|
+
```
|
36
|
+
|
37
|
+
* Import it into Java cacerts:
|
38
|
+
```sh
|
39
|
+
$JAVA_HOME/bin/keytool -keystore $JAVA_HOME/lib/security/cacerts -importcert -alias ciscoips -file cert.pem
|
40
|
+
```
|
41
|
+
|
42
|
+
* Verify if import was successful:
|
43
|
+
```sh
|
44
|
+
$JAVA_HOME/bin/keytool -keystore $JAVA_HOME/lib/security/cacerts -list
|
45
|
+
```
|
46
|
+
|
47
|
+
* Modify your logstash input config for SSL connection:
|
48
|
+
```ruby
|
49
|
+
input {
|
50
|
+
sdee {
|
51
|
+
interval => 60
|
52
|
+
http => {
|
53
|
+
truststore_password => "changeit"
|
54
|
+
url => "https://10.0.2.1"
|
55
|
+
auth => {
|
56
|
+
user => "cisco"
|
57
|
+
password => "p@ssw0rd"
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
```
|
63
|
+
|
64
|
+
* Test logstash
|
65
|
+
|
66
|
+
## Documentation
|
67
|
+
|
68
|
+
Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elasticsearch.org/guide/en/logstash/current/).
|
69
|
+
|
70
|
+
- For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
|
71
|
+
- For more asciidoc formatting tips, see the excellent reference here https://github.com/elasticsearch/docs#asciidoc-guide
|
72
|
+
|
73
|
+
## Need Help?
|
74
|
+
|
75
|
+
Need help? Try #logstash on freenode IRC or the https://discuss.elastic.co/c/logstash discussion forum.
|
76
|
+
|
77
|
+
## Developing
|
78
|
+
|
79
|
+
### 1. Plugin Developement and Testing
|
80
|
+
|
81
|
+
#### Code
|
82
|
+
- To get started, you'll need JRuby with the Bundler gem installed.
|
83
|
+
|
84
|
+
- Create a new plugin or clone and existing from the GitHub [logstash-plugins](https://github.com/logstash-plugins) organization. We also provide [example plugins](https://github.com/logstash-plugins?query=example).
|
85
|
+
|
86
|
+
- Install dependencies
|
87
|
+
```sh
|
88
|
+
bundle install
|
89
|
+
```
|
90
|
+
|
91
|
+
#### Test
|
92
|
+
|
93
|
+
- Update your dependencies
|
94
|
+
|
95
|
+
```sh
|
96
|
+
bundle install
|
97
|
+
```
|
98
|
+
|
99
|
+
- Run tests
|
100
|
+
|
101
|
+
```sh
|
102
|
+
bundle exec rspec
|
103
|
+
```
|
104
|
+
|
105
|
+
### 2. Running your unpublished Plugin in Logstash
|
106
|
+
|
107
|
+
#### 2.1 Run in a local Logstash clone
|
108
|
+
|
109
|
+
- Edit Logstash `Gemfile` and add the local plugin path, for example:
|
110
|
+
```ruby
|
111
|
+
gem "logstash-input-sdee", :path => "/your/local/logstash-input-sdee"
|
112
|
+
```
|
113
|
+
- Install plugin
|
114
|
+
```sh
|
115
|
+
bin/plugin install --no-verify
|
116
|
+
```
|
117
|
+
- Run Logstash with your plugin
|
118
|
+
```sh
|
119
|
+
bin/logstash -e 'input {sdee { interval => 60 http => { url => "http://ciscoips" auth => {user => "cisco" password => "p@ssw0rd"}} session_file => "/tmp/session.db" }}'
|
120
|
+
```
|
121
|
+
At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
|
122
|
+
|
123
|
+
Enable signature 2000 (ICMP Echo Reply) on your Cisco IPS device and ping some host on a network, monitored by IPS.
|
124
|
+
You should see output like this:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
{
|
128
|
+
"@timestamp" => "2015-09-21T12:21:26.000Z",
|
129
|
+
"timezone" => "EEST",
|
130
|
+
"tz_offset" => "180",
|
131
|
+
"event_id" => "6824288790867",
|
132
|
+
"severity" => "informational",
|
133
|
+
"vendor" => "Cisco",
|
134
|
+
"host_id" => "sensor1",
|
135
|
+
"app_name" => "sensorApp",
|
136
|
+
"app_instance_id" => "26957",
|
137
|
+
"description" => "ICMP Echo Reply",
|
138
|
+
"sig_id" => "2000",
|
139
|
+
"sig_version" => "S666",
|
140
|
+
"sig_type" => "other",
|
141
|
+
"sig_created" => "20001127",
|
142
|
+
"subsig_id" => "0",
|
143
|
+
"sig_details" => "ICMP Echo Reply",
|
144
|
+
"interface_group" => "vs0",
|
145
|
+
"vlan" => "0",
|
146
|
+
"attacker_addr" => "10.0.0.1",
|
147
|
+
"attacker_locality" => "OUT",
|
148
|
+
"target_addr" => "10.0.1.1",
|
149
|
+
"target_os_source" => "learned",
|
150
|
+
"target_os_type" => "windows-nt-2k-xp",
|
151
|
+
"target_os_relevance" => "relevant",
|
152
|
+
"alert_details" => "InterfaceAttributes: context='single_vf' physical='Unknown' backplane='PortChannel0/0' ; ",
|
153
|
+
"risk_rating" => "35",
|
154
|
+
"risk_target" => "medium",
|
155
|
+
"risk_attacker" => "relevant",
|
156
|
+
"threat_rating" => "35",
|
157
|
+
"interface" => "PortChannel0/0",
|
158
|
+
"host" => "10.0.2.1",
|
159
|
+
"tags" => "SDEE",
|
160
|
+
"message" => "IdsAlert: 'ICMP Echo Reply' Attacker: '10.0.0.1' Target: '10.0.1.1' SigId: '2000'",
|
161
|
+
"@version" => "1"
|
162
|
+
}
|
163
|
+
```
|
164
|
+
|
165
|
+
#### 2.2 Run in an installed Logstash
|
166
|
+
|
167
|
+
You can use the same **2.1** method to run your plugin in an installed Logstash by editing its `Gemfile` and pointing the `:path` to your local plugin development directory or you can build the gem and install it using:
|
168
|
+
|
169
|
+
- Build your plugin gem
|
170
|
+
```sh
|
171
|
+
gem build logstash-input-sdee.gemspec
|
172
|
+
```
|
173
|
+
- Install the plugin from the Logstash home
|
174
|
+
```sh
|
175
|
+
bin/plugin install /your/local/plugin/logstash-input-sdee.gem
|
176
|
+
```
|
177
|
+
- Start Logstash and proceed to test the plugin
|
178
|
+
|
179
|
+
## Contributing
|
180
|
+
|
181
|
+
All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
|
182
|
+
|
183
|
+
Programming is not a required skill. Whatever you've seen about open source and maintainers or community members saying "send patches or die" - you will not see that here.
|
184
|
+
|
185
|
+
It is more important to the community that you are able to contribute.
|
186
|
+
|
187
|
+
For more information about contributing, see the [CONTRIBUTING](https://github.com/elasticsearch/logstash/blob/master/CONTRIBUTING.md) file.
|
188
|
+
|
189
|
+
## Reference
|
190
|
+
[Cisco Intrusion Detection Event Exchange (CIDEE) Specification](http://www.cisco.com/c/en/us/td/docs/security/ips/specs/CIDEE_Specification.html)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#== Cisco ASA ==
|
2
|
+
HOSTNAME \b(?:[_0-9A-Za-z][_0-9A-Za-z-]{0,62})(?:\.(?:[_0-9A-Za-z][_0-9A-Za-z-]{0,62}))*(\.?|\b)
|
3
|
+
CTIMESTAMP %{YEAR}-%{MONTHNUM2}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?
|
4
|
+
CISCO_TAGGED %{CTIMESTAMP:ctimestamp}( %{SYSLOGHOST:sysloghost})? %{CISCO_TAG:ciscotag}:
|
5
|
+
CISCO_TAG %[A-Z0-9]+-%{INT:cisco_severity}-(?:[A-Z0-9_]+)|WLC[0-9]+
|
6
|
+
# Common Particles
|
7
|
+
CISCO_ASA_ACTION Built|Teardown|Deny|Denied|denied|requested|permitted|received|denied by ACL|discarded|est-allowed|Dropping|created|deleted|SENDING|RECEIVED|monitored|dropped
|
8
|
+
CISCO_ASA_REASON Duplicate TCP SYN|TCP Reset\-O|Failed to locate egress interface|Invalid transport field|No matching connection|DNS Response|DNS Query|(?:%{WORD}\s*)*
|
9
|
+
CISCO_ASA_DIRECTION Inbound|inbound|Outbound|outbound
|
10
|
+
CISCO_ASA_INTERVAL first hit|%{INT}-second interval
|
11
|
+
CISCO_ASA_XLATE_TYPE static|dynamic
|
12
|
+
# ASA-2-106001
|
13
|
+
CISCOASA106001 %{CISCO_ASA_DIRECTION:direction} %{WORD:protocol} connection %{CISCO_ASA_ACTION:action} from %{IP:src_ip}/%{INT:src_port} to %{IP:dst_ip}/%{INT:dst_port} flags %{GREEDYDATA:tcp_flags} on interface %{GREEDYDATA:interface}
|
14
|
+
# ASA-2-106006, ASA-2-106007, ASA-2-106010
|
15
|
+
CISCOASA106006_106007_106010 %{CISCO_ASA_ACTION:action} %{CISCO_ASA_DIRECTION:direction} %{WORD:protocol} (?:from|src) %{IP:src_ip}/%{INT:src_port}(\(%{DATA:src_fwuser}\))? (?:to|dst) %{IP:dst_ip}/%{INT:dst_port}(\(%{DATA:dst_fwuser}\))? (?:on interface %{DATA:interface}|due to %{CISCO_ASA_REASON:reason})
|
16
|
+
# ASA-3-106014
|
17
|
+
CISCOASA106014 %{CISCO_ASA_ACTION:action} %{CISCO_ASA_DIRECTION:direction} %{WORD:protocol} src %{DATA:src_interface}:%{IP:src_ip}(\(%{DATA:src_fwuser}\))? dst %{DATA:dst_interface}:%{IP:dst_ip}(\(%{DATA:dst_fwuser}\))? \(type %{INT:icmp_type}, code %{INT:icmp_code}\)
|
18
|
+
# ASA-6-106015
|
19
|
+
CISCOASA106015 %{CISCO_ASA_ACTION:action} %{WORD:protocol} \(%{DATA:policy_id}\) from %{IPORHOST:src_ip}/%{INT:src_port} to %{IPORHOST:dst_ip}/%{INT:dst_port} flags %{DATA:tcp_flags} on interface %{GREEDYDATA:interface}
|
20
|
+
# ASA-1-106021
|
21
|
+
CISCOASA106021 %{CISCO_ASA_ACTION:action} %{WORD:protocol} reverse path check from %{IP:src_ip} to %{IP:dst_ip} on interface %{GREEDYDATA:interface}
|
22
|
+
# ASA-4-106023
|
23
|
+
CISCOASA106023 %{CISCO_ASA_ACTION:action} %{WORD:protocol} src %{DATA:src_interface}:%{IPORHOST:src_ip}(/%{INT:src_port})?(\(%{DATA:src_fwuser}\))? dst %{DATA:dst_interface}:%{IPORHOST:dst_ip}(/%{INT:dst_port})?(\(%{DATA:dst_fwuser}\))?( \(type %{INT:icmp_type}, code %{INT:icmp_code}\))? by access-group %{DATA:policy_id} \[%{DATA:hashcode1}, %{DATA:hashcode2}\]
|
24
|
+
# ASA-5-106100
|
25
|
+
CISCOASA106100 access-list %{WORD:policy_id} %{CISCO_ASA_ACTION:action} %{WORD:protocol} %{DATA:src_interface}/%{IP:src_ip}\(%{INT:src_port}\)(\(%{DATA:src_fwuser}\))? -> %{DATA:dst_interface}/%{IP:dst_ip}\(%{INT:dst_port}\)(\(%{DATA:src_fwuser}\))? hit-cnt %{INT:hit_count} %{CISCO_ASA_INTERVAL:interval} \[%{DATA:hashcode1}, %{DATA:hashcode2}\]
|
26
|
+
# ASA-6-110002
|
27
|
+
CISCOASA110002 %{CISCO_ASA_REASON:reason} for %{WORD:protocol} from %{DATA:src_interface}:%{IPORHOST:src_ip}/%{INT:src_port} to %{IP:dst_ip}/%{INT:dst_port}
|
28
|
+
# ASA-5-111008
|
29
|
+
CISCOASA111008 User \'%{DATA:src_fwuser}\' executed the \'%{GREEDYDATA:cmd}\' command\.
|
30
|
+
# ASA-7-111009
|
31
|
+
CISCOASA111009 User \'%{DATA:src_fwuser}\' executed cmd: %{GREEDYDATA:cmd}
|
32
|
+
# ASA-5-111010
|
33
|
+
CISCOASA111010 User \'%{DATA:src_fwuser}\', running \'CLI\' from IP %{IPORHOST:src_ip}, executed \'%{GREEDYDATA:cmd}\'
|
34
|
+
# ASA-6-302010
|
35
|
+
CISCOASA302010 %{INT:connection_count} in use, %{INT:connection_count_max} most used
|
36
|
+
# ASA-6-302013, ASA-6-302014, ASA-6-302015, ASA-6-302016
|
37
|
+
CISCOASA302013_302014_302015_302016 %{CISCO_ASA_ACTION:action}(?: %{CISCO_ASA_DIRECTION:direction})? %{WORD:protocol} connection %{INT:connection_id} for %{DATA:src_interface}:%{IPORHOST:src_ip}/%{INT:src_port}( \(%{IPORHOST:src_mapped_ip}/%{INT:src_mapped_port}\))?(\(%{DATA:src_fwuser}\))? to %{DATA:dst_interface}:%{IPORHOST:dst_ip}/%{INT:dst_port}( \(%{IPORHOST:dst_mapped_ip}/%{INT:dst_mapped_port}\))?(\(%{DATA:dst_fwuser}\))?( duration %{TIME:duration} bytes %{INT:bytes})?(?: %{CISCO_ASA_REASON:reason})?( \(%{DATA:user}\))?
|
38
|
+
# ASA-6-302020, ASA-6-302021
|
39
|
+
CISCOASA302020_302021 %{CISCO_ASA_ACTION:action}(?: %{CISCO_ASA_DIRECTION:direction})? %{WORD:protocol} connection for faddr %{IPORHOST:dst_ip}/%{INT:icmp_seq_num}(?:\(%{DATA:fwuser}\))? gaddr %{IPORHOST:src_xlated_ip}/%{INT:icmp_code_xlated} laddr %{IPORHOST:src_ip}/%{INT:icmp_code}( \(%{DATA:user}\))?
|
40
|
+
# ASA-3-305006
|
41
|
+
CISCOASA305006 regular translation creation failed for %{WORD:protocol} src %{DATA:src_interface}:%{IPORHOST:src_ip}(/%{INT:src_port})? dst %{DATA:dst_interface}:%{IPORHOST:dst_ip}(/%{INT:dst_port})?(?: \(type %{INT:icmp_type}, code %{INT:icmp_code}\))?
|
42
|
+
# ASA-6-305011
|
43
|
+
CISCOASA305011 %{CISCO_ASA_ACTION:action} %{CISCO_ASA_XLATE_TYPE:xlate_type} %{WORD:protocol} translation from %{DATA:src_interface}:%{IPORHOST:src_ip}(/%{INT:src_port})?(\(%{DATA:src_fwuser}\))? to %{DATA:src_xlated_interface}:%{IPORHOST:src_xlated_ip}/%{DATA:src_xlated_port}
|
44
|
+
# ASA-5-305013
|
45
|
+
CISCOASA305013 Asymmetric NAT rules matched for forward and reverse flows; Connection for %{WORD:protocol} src %{DATA:src_interface}:%{IPORHOST:src_ip}(/%{INT:src_port})? dst %{DATA:dst_interface}:%{IPORHOST:dst_ip}(/%{INT:dst_port})? %{CISCO_ASA_ACTION:action} due to NAT reverse path failure
|
46
|
+
# ASA-3-313001, ASA-3-313004, ASA-3-313008
|
47
|
+
CISCOASA313001_313004_313008 %{CISCO_ASA_ACTION:action} %{WORD:protocol} type=%{INT:icmp_type}, code=%{INT:icmp_code} from %{IP:src_ip} on interface %{DATA:interface}( to %{IP:dst_ip})?
|
48
|
+
# ASA-4-313005
|
49
|
+
CISCOASA313005 %{CISCO_ASA_REASON:reason} for %{WORD:protocol} error message: %{WORD:err_protocol} src %{DATA:err_src_interface}:%{IPORHOST:err_src_ip}(\(%{DATA:err_src_fwuser}\))? dst %{DATA:err_dst_interface}:%{IPORHOST:err_dst_ip}(\(%{DATA:err_dst_fwuser}\))? \(type %{INT:err_icmp_type}, code %{INT:err_icmp_code}\) on %{DATA:interface} interface\. Original IP payload: %{WORD:protocol} src %{IPORHOST:orig_src_ip}/%{INT:orig_src_port}(\(%{DATA:orig_src_fwuser}\))? dst %{IPORHOST:orig_dst_ip}/%{INT:orig_dst_port}(\(%{DATA:orig_dst_fwuser}\))?
|
50
|
+
# ASA-4-338004, ASA-4-338008
|
51
|
+
CISCOASA338004_338008 Dynamic Filter %{CISCO_ASA_ACTION:action} blacklisted %{WORD:protocol} traffic from %{DATA:src_interface}:%{IPORHOST:src_ip}(/%{INT:src_port})?( \(%{IPORHOST:src_mapped_ip}/%{INT:src_mapped_port}\))? to %{DATA:dst_interface}:%{IPORHOST:dst_ip}(/%{INT:dst_port})?( \(%{IPORHOST:dst_mapped_ip}/%{INT:dst_mapped_port}\))?, destination %{IPORHOST:blacklisted_ip} resolved from local list: %{IPORHOST:blacklisted_ip}/%{IPORHOST:blacklisted_netmask}, threat-level: %{DATA:threat_level}, category: %{DATA:category}
|
52
|
+
# ASA-4-338008 Dynamic Filter %{CISCO_ASA_ACTION:action} blacklisted %{WORD:protocol} traffic from %{DATA:src_interface}:%{IPORHOST:src_ip}(/%{INT:src_port})?( \(%{IPORHOST:src_mapped_ip}/%{INT:src_mapped_port}\))? to %{DATA:dst_interface}:%{IPORHOST:dst_ip}(/%{INT:dst_port})?( \(%{IPORHOST:dst_mapped_ip}/%{INT:dst_mapped_port}\))?, destination %{IPORHOST:blacklisted_ip} resolved from local list: 221.204.186.0/255.255.255.0, threat-level: very-high, category: admin-added
|
53
|
+
# ASA-4-402117
|
54
|
+
CISCOASA402117 %{WORD:protocol}: Received a non-IPSec packet \(protocol= %{WORD:orig_protocol}\) from %{IP:src_ip} to %{IP:dst_ip}
|
55
|
+
# ASA-4-402119
|
56
|
+
CISCOASA402119 %{WORD:protocol}: Received an %{WORD:orig_protocol} packet \(SPI= %{DATA:spi}, sequence number= %{DATA:seq_num}\) from %{IP:src_ip} \(user= %{DATA:user}\) to %{IP:dst_ip} that failed anti-replay checking
|
57
|
+
# ASA-4-419001
|
58
|
+
CISCOASA419001 %{CISCO_ASA_ACTION:action} %{WORD:protocol} packet from %{DATA:src_interface}:%{IP:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IP:dst_ip}/%{INT:dst_port}, reason: %{GREEDYDATA:reason}
|
59
|
+
# ASA-4-419002
|
60
|
+
CISCOASA419002 %{CISCO_ASA_REASON:reason} from %{DATA:src_interface}:%{IPORHOST:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IPORHOST:dst_ip}/%{INT:dst_port} with different initial sequence number
|
61
|
+
# ASA-4-500004
|
62
|
+
CISCOASA500004 %{CISCO_ASA_REASON:reason} for protocol=%{WORD:protocol}, from %{IP:src_ip}/%{INT:src_port} to %{IP:dst_ip}/%{INT:dst_port}
|
63
|
+
# ASA-6-602303, ASA-6-602304
|
64
|
+
CISCOASA602303_602304 %{WORD:protocol}: An %{CISCO_ASA_DIRECTION:direction} %{GREEDYDATA:tunnel_type} SA \(SPI= %{DATA:spi}\) between %{IP:src_ip} and %{IP:dst_ip} \(user= %{DATA:user}\) has been %{CISCO_ASA_ACTION:action}
|
65
|
+
# ASA-7-609001, ASA-7-609002
|
66
|
+
CISCOASA609001_609002 %{CISCO_ASA_ACTION:action} local-host %{DATA:src_interface}:%{IPORHOST:src_ip}(?: duration %{TIME:duration})?
|
67
|
+
# ASA-7-710001, ASA-7-710002, ASA-7-710003, ASA-7-710005, ASA-7-710006
|
68
|
+
CISCOASA710001_710002_710003_710005_710006_710007 %{WORD:protocol} (?:request|access|keepalive) %{CISCO_ASA_ACTION:action} from %{IPORHOST:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IPORHOST:dst_ip}/%{DATA:dst_port}
|
69
|
+
# ASA-6-713172
|
70
|
+
CISCOASA713172 Group = %{GREEDYDATA:group}, IP = %{IP:src_ip}, Automatic NAT Detection Status:\s+Remote end\s*%{DATA:is_remote_natted}\s*behind a NAT device\s+This\s+end\s*%{DATA:is_local_natted}\s*behind a NAT device
|
71
|
+
# ASA-7-713236
|
72
|
+
CISCOASA713236 IP = %{IPORHOST:src_ip}, IKE_DECODE %{CISCO_ASA_ACTION} Message \(msgid=%{DATA:msgid}\) with payloads : %{GREEDYDATA:payload} total length : %{INT:length}
|
73
|
+
# ASA-7-713906
|
74
|
+
CISCOASA713906 IKE Receiver: Packet received on %{IPORHOST:dst_ip}:%{INT:dst_port} from %{IPORHOST:src_ip}:%{INT:src_port}
|
75
|
+
# ASA-7-715046
|
76
|
+
CISCOASA715036_715046_715047_715075 Group = %{GREEDYDATA:group},(?: Username = %{DATA:src_fwuser},)? IP = %{IP:src_ip},%{GREEDYDATA:vpn_action}
|
77
|
+
# ASA-4-733100
|
78
|
+
CISCOASA733100 \[\s*%{DATA:drop_type}\s*\] drop %{DATA:drop_rate_id} exceeded. Current burst rate is %{INT:drop_rate_current_burst} per second, max configured rate is %{INT:drop_rate_max_burst}; Current average rate is %{INT:drop_rate_current_avg} per second, max configured rate is %{INT:drop_rate_max_avg}; Cumulative total count is %{INT:drop_total_count}
|
79
|
+
#== End Cisco ASA ==
|
data/examples/sdee.conf
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
input {
|
2
|
+
|
3
|
+
sdee {
|
4
|
+
type => "sdee"
|
5
|
+
interval => 60
|
6
|
+
http => {
|
7
|
+
url => "http://ciscoips1"
|
8
|
+
auth => {
|
9
|
+
user => "cisco"
|
10
|
+
password => "p@ssw0rd"
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
sdee {
|
16
|
+
type => "sdee"
|
17
|
+
interval => 60
|
18
|
+
http => {
|
19
|
+
url => "https://ciscoips2"
|
20
|
+
# do not forget, you must add your device or CA certificate to Java trustStore. See README.md
|
21
|
+
truststore_password => "changeit"
|
22
|
+
auth => {
|
23
|
+
user => "cisco"
|
24
|
+
password => "p@ssw0rd"
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
}
|
30
|
+
|
31
|
+
output {
|
32
|
+
stdout {
|
33
|
+
codec => rubydebug
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,354 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/inputs/base"
|
3
|
+
require "logstash/namespace"
|
4
|
+
require "logstash/plugin_mixins/http_client"
|
5
|
+
|
6
|
+
require "yaml"
|
7
|
+
require "uri"
|
8
|
+
require "pathname"
|
9
|
+
require "time"
|
10
|
+
require "rexml/document"
|
11
|
+
require "socket" # for Socket.gethostname
|
12
|
+
require "manticore"
|
13
|
+
include REXML
|
14
|
+
|
15
|
+
class LogStash::Inputs::SDEE < LogStash::Inputs::Base
|
16
|
+
include LogStash::PluginMixins::HttpClient
|
17
|
+
|
18
|
+
config_name "sdee"
|
19
|
+
# Do we really need a codec?
|
20
|
+
# default :codec, "plain"
|
21
|
+
|
22
|
+
# A Hash of urls in this format : "name" => "url"
|
23
|
+
# The name and the url will be passed in the outputed event
|
24
|
+
#
|
25
|
+
config :http, :validate => :hash, :required => true
|
26
|
+
|
27
|
+
# How often (in seconds) the urls will be called
|
28
|
+
config :interval, :validate => :number, :required => true
|
29
|
+
|
30
|
+
# If you'd like to work with the request/response metadata
|
31
|
+
# Set this value to the name of the field you'd like to store a nested
|
32
|
+
# hash of metadata.
|
33
|
+
config :metadata_target, :validate => :string, :default => '@metadata'
|
34
|
+
#, :default => '@metadata'
|
35
|
+
|
36
|
+
# A path to store tempfile with SDEE SubscriptionID and SessionID
|
37
|
+
config :session_path, :validate => :string, :default => '/tmp'
|
38
|
+
|
39
|
+
public
|
40
|
+
def register
|
41
|
+
@host = Socket.gethostname.force_encoding(Encoding::UTF_8)
|
42
|
+
@session_file = Pathname.new(@session_path) + "temp#{URI.parse(@http["url"]).host}.db"
|
43
|
+
@remaining = 0
|
44
|
+
setup_request!(@http)
|
45
|
+
|
46
|
+
@logger.info("Registering SDEE Input", :type => @type,
|
47
|
+
:http => @http, :interval => @interval, :timeout => @timeout)
|
48
|
+
|
49
|
+
#subscribe to SDEE and store session data
|
50
|
+
@session = subscribe(@request)
|
51
|
+
|
52
|
+
newurl = URI.join(@http["url"], "cgi-bin/sdee-server?subscriptionId=#{@session[:subscriptionid]}&confirm=yes&maxNbrOfEvents=150&timeout=5&sessionId=#{@session[:sessionid]}")
|
53
|
+
|
54
|
+
@request[1] = newurl.to_s
|
55
|
+
rescue StandardError, java.lang.Exception => e
|
56
|
+
@logger.error? && @logger.error("SDEE subscription error!",
|
57
|
+
:exception => e,
|
58
|
+
:exception_message => e.message,
|
59
|
+
:exeption_backtrace => e.backtrace
|
60
|
+
)
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def subscribe(request)
|
66
|
+
# recover from ungraceful shutdown first
|
67
|
+
if @session_file.exist?
|
68
|
+
yaml = YAML.load_file(@session_file)
|
69
|
+
if (defined?(yaml) && yaml != nil)
|
70
|
+
unsubscribe(request,yaml)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
url = URI.join(@http["url"], "cgi-bin/sdee-server?action=open&evIdsAlert&force=yes")
|
75
|
+
request[1] = url.to_s
|
76
|
+
session = Hash.new
|
77
|
+
method, *request_opts = request
|
78
|
+
client.async.send(method, *request_opts).
|
79
|
+
on_success {|response| session = handle_subscription(request, response)}.
|
80
|
+
on_failure {|exception| http_error(request, exception)}
|
81
|
+
client.execute!
|
82
|
+
raise LogStash::ConfigurationError, "SDEE subscription Error! Check your configuration for host url,user,password." unless session
|
83
|
+
session
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
def handle_subscription(request, response)
|
88
|
+
body = response.body
|
89
|
+
xml = REXML::Document.new body.to_s
|
90
|
+
session = Hash.new
|
91
|
+
sessionid = REXML::XPath.first(xml, "//sd:sessionId")
|
92
|
+
subscriptionid = REXML::XPath.first(xml, "//sd:subscriptionId")
|
93
|
+
session[:sessionid] = sessionid.text if sessionid
|
94
|
+
session[:subscriptionid] = subscriptionid.text if subscriptionid
|
95
|
+
File.open(@session_file, 'w') {|f| f.write session.to_yaml}
|
96
|
+
session
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
def http_error(request, exeption)
|
101
|
+
@logger.error? && @logger.error("Cannot read URL or send the error as an event! Check your configuration for host url,user,password.",
|
102
|
+
:request => structure_request(request),
|
103
|
+
:exception => exeption.to_s,
|
104
|
+
:exception_backtrace => exeption.backtrace
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
def unsubscribe(request,session)
|
110
|
+
#unsubscribe and remove session data file
|
111
|
+
url = URI.join(@http["url"], "cgi-bin/sdee-server?action=close&subscriptionId=#{session[:subscriptionid]}&sessionId=#{session[:sessionid]}")
|
112
|
+
request[1] = url.to_s
|
113
|
+
method, *request_opts = request
|
114
|
+
client.async.send(method, *request_opts).
|
115
|
+
on_success {|response| remove_session}.
|
116
|
+
on_failure {|exception| http_error(request, exception)}
|
117
|
+
client.execute!
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
def remove_session
|
122
|
+
if @session_file.exist?
|
123
|
+
@session_file.unlink
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
def setup_request!(http)
|
129
|
+
@request = normalize_request(http)
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
def normalize_request(http)
|
134
|
+
if http.is_a?(Hash)
|
135
|
+
# The client will expect keys / values
|
136
|
+
spec = Hash[http.clone.map {|k,v| [k.to_sym, v] }] # symbolize keys
|
137
|
+
|
138
|
+
# method and url aren't really part of the options, so we pull them out
|
139
|
+
method = (spec.delete(:method) || :get).to_sym.downcase
|
140
|
+
url = spec.delete(:url)
|
141
|
+
|
142
|
+
# We need these strings to be keywords!
|
143
|
+
spec[:auth] = {user: spec[:auth]["user"], pass: spec[:auth]["password"]} if spec[:auth]
|
144
|
+
res = [method, url, spec]
|
145
|
+
else
|
146
|
+
raise LogStash::ConfigurationError, "Invalid request spec: '#{http}', expected a Hash!"
|
147
|
+
end
|
148
|
+
|
149
|
+
validate_request!(http, res)
|
150
|
+
res
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
def validate_request!(http, request)
|
155
|
+
method, url, spec = request
|
156
|
+
|
157
|
+
raise LogStash::ConfigurationError, "No URL provided for request! #{http}" unless url
|
158
|
+
if spec && spec[:auth]
|
159
|
+
if !spec[:auth][:user]
|
160
|
+
raise LogStash::ConfigurationError, "Auth was specified, but 'user' was not!"
|
161
|
+
end
|
162
|
+
if !spec[:auth][:pass]
|
163
|
+
raise LogStash::ConfigurationError, "Auth was specified, but 'password' was not!"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
request
|
168
|
+
end
|
169
|
+
|
170
|
+
public
|
171
|
+
def run(queue)
|
172
|
+
while true
|
173
|
+
begin
|
174
|
+
Stud.interval(@interval) do
|
175
|
+
begin
|
176
|
+
run_once(queue)
|
177
|
+
end while (@remaining > 0)
|
178
|
+
end
|
179
|
+
rescue EOFError, LogStash::ShutdownSignal
|
180
|
+
break
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
public
|
186
|
+
def teardown
|
187
|
+
@logger.debug? && @logger.debug("SDEE shutting down")
|
188
|
+
unsubscribe(@request,@session) rescue nil
|
189
|
+
finished
|
190
|
+
end # def teardown
|
191
|
+
|
192
|
+
private
|
193
|
+
def run_once(queue)
|
194
|
+
request_async(queue, @request)
|
195
|
+
client.execute!
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
def request_async(queue, request)
|
200
|
+
@logger.debug? && @logger.debug("Fetching URL", :url => request)
|
201
|
+
started = Time.now
|
202
|
+
|
203
|
+
method, *request_opts = request
|
204
|
+
client.async.send(method, *request_opts).
|
205
|
+
on_success {|response| handle_success(queue, request, response, Time.now - started)}.
|
206
|
+
on_failure {|exception| handle_failure(queue, request, exception, Time.now - started)
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
def handle_success(queue, request, response, execution_time)
|
212
|
+
decode(response.body).each_pair do |id,decoded|
|
213
|
+
event = LogStash::Event.new(decoded)
|
214
|
+
handle_decoded_event(queue, request, response, event, execution_time)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
def handle_decoded_event(queue, request, response, event, execution_time)
|
220
|
+
apply_metadata(event, request, response, execution_time) if @metadata_target
|
221
|
+
decorate(event)
|
222
|
+
queue << event
|
223
|
+
rescue StandardError, java.lang.Exception => e
|
224
|
+
@logger.error? && @logger.error("Error eventifying response!",
|
225
|
+
:exception => e,
|
226
|
+
:exception_message => e.message,
|
227
|
+
:exeption_backtrace => e.backtrace,
|
228
|
+
:url => request,
|
229
|
+
:response => response
|
230
|
+
)
|
231
|
+
end
|
232
|
+
|
233
|
+
private
|
234
|
+
# Beware, on old versions of manticore some uncommon failures are not handled
|
235
|
+
def handle_failure(queue, request, exception, execution_time)
|
236
|
+
event = LogStash::Event.new
|
237
|
+
apply_metadata(event, request)
|
238
|
+
|
239
|
+
event.tag("_sdee_failure")
|
240
|
+
|
241
|
+
# This is also in the metadata, but we send it anyone because we want this
|
242
|
+
# persisted by default, whereas metadata isn't. People don't like mysterious errors
|
243
|
+
event["sdee_failure"] = {
|
244
|
+
"request" => structure_request(request),
|
245
|
+
"error" => exception.to_s,
|
246
|
+
"backtrace" => exception.backtrace,
|
247
|
+
"runtime_seconds" => execution_time
|
248
|
+
}
|
249
|
+
|
250
|
+
queue << event
|
251
|
+
rescue StandardError, java.lang.Exception => e
|
252
|
+
@logger.error? && @logger.error("Cannot read URL or send the error as an event!",
|
253
|
+
:exception => e,
|
254
|
+
:exception_message => e.message,
|
255
|
+
:exception_backtrace => e.backtrace,
|
256
|
+
:url => request
|
257
|
+
)
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
def apply_metadata(event, request, response=nil, execution_time=nil)
|
262
|
+
#return unless @metadata_target
|
263
|
+
event[@metadata_target] = event_metadata(request, response, execution_time)
|
264
|
+
end
|
265
|
+
|
266
|
+
private
|
267
|
+
def event_metadata(request, response=nil, execution_time=nil)
|
268
|
+
m = {
|
269
|
+
"host" => @host,
|
270
|
+
"request" => structure_request(request),
|
271
|
+
}
|
272
|
+
|
273
|
+
m["runtime_seconds"] = execution_time
|
274
|
+
|
275
|
+
if response
|
276
|
+
m["code"] = response.code
|
277
|
+
m["response_headers"] = response.headers
|
278
|
+
m["response_message"] = response.message
|
279
|
+
m["times_retried"] = response.times_retried
|
280
|
+
end
|
281
|
+
m
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
# Turn [method, url, spec] requests into a hash for friendlier logging / ES indexing
|
286
|
+
def structure_request(request)
|
287
|
+
method, url, spec = request
|
288
|
+
# Flatten everything into the 'spec' hash, also stringify any keys to normalize
|
289
|
+
Hash[(spec||{}).merge({
|
290
|
+
"method" => method.to_s,
|
291
|
+
"url" => url,
|
292
|
+
}).map {|k,v| [k.to_s,v] }]
|
293
|
+
end
|
294
|
+
|
295
|
+
private
|
296
|
+
def decode(body)
|
297
|
+
events = Hash.new
|
298
|
+
xml = REXML::Document.new body.to_s
|
299
|
+
err = REXML::XPath.first(xml, "//env:Reason") if REXML::XPath.first(xml, "//env:Fault")
|
300
|
+
err = err.text.to_s if err
|
301
|
+
if err && err == "Subscription does not exist"
|
302
|
+
subscribe(@request)
|
303
|
+
end
|
304
|
+
rem = REXML::XPath.first(xml, "//sd:remaining-events")
|
305
|
+
@remaining = rem.text.to_i if rem
|
306
|
+
# We use own XML parsing to keep things simple to the user
|
307
|
+
xml.elements.each("*/env:Body/sd:events/sd:evIdsAlert") do |element|
|
308
|
+
eid = element.attributes["eventId"]
|
309
|
+
# Get timestamp in nsec from sensor
|
310
|
+
timestamp=REXML::XPath.first(element,"./sd:time").text.to_i(10)
|
311
|
+
events[eid] = {
|
312
|
+
"@timestamp" => Time.at(timestamp/10**9,((timestamp%10**9)/1000).to_f).iso8601(3),
|
313
|
+
"timezone" => REXML::XPath.first(element,"./sd:time").attributes["timeZone"],
|
314
|
+
"tz_offset" => REXML::XPath.first(element,"./sd:time").attributes["offset"],
|
315
|
+
"event_id" => eid.to_s,
|
316
|
+
"severity" => element.attributes["severity"].to_s.capitalize,
|
317
|
+
"vendor" => element.attributes["vendor"].to_s,
|
318
|
+
"host_id" => REXML::XPath.first(element,"./sd:originator/sd:hostId").text,
|
319
|
+
"app_name" => REXML::XPath.first(element,"./sd:originator/cid:appName").text,
|
320
|
+
"app_instance_id" => REXML::XPath.first(element,"./sd:originator/cid:appInstanceId").text,
|
321
|
+
"description" => REXML::XPath.first(element,"./sd:signature").attributes["description"],
|
322
|
+
"sig_id" => REXML::XPath.first(element,"./sd:signature").attributes["id"],
|
323
|
+
"sig_version" => REXML::XPath.first(element,"./sd:signature").attributes["cid:version"],
|
324
|
+
"sig_type" => REXML::XPath.first(element,"./sd:signature").attributes["cid:type"],
|
325
|
+
"sig_created" => REXML::XPath.first(element,"./sd:signature").attributes["created"],
|
326
|
+
"subsig_id" => REXML::XPath.first(element,"./sd:signature/cid:subsigId").text,
|
327
|
+
"sig_details" => REXML::XPath.first(element,"./sd:signature/cid:sigDetails").text,
|
328
|
+
"interface_group" => REXML::XPath.first(element,"./sd:interfaceGroup").text,
|
329
|
+
"vlan" => REXML::XPath.first(element,"./sd:vlan").text,
|
330
|
+
"attacker_addr" => REXML::XPath.first(element,"./sd:participants/sd:attacker/sd:addr").text,
|
331
|
+
"attacker_locality" => REXML::XPath.first(element,"./sd:participants/sd:attacker/sd:addr").attributes["locality"],
|
332
|
+
"target_addr" => REXML::XPath.first(element,"./sd:participants/sd:target/sd:addr").text,
|
333
|
+
"targed_locality" => REXML::XPath.first(element,"./sd:participants/sd:target/sd:addr").attributes["locality"],
|
334
|
+
"target_os_source" => REXML::XPath.first(element,"./sd:participants/sd:target/cid:os").attributes["idSource"],
|
335
|
+
"target_os_type" => REXML::XPath.first(element,"./sd:participants/sd:target/cid:os").attributes["type"],
|
336
|
+
"target_os_relevance" => REXML::XPath.first(element,"./sd:participants/sd:target/cid:os").attributes["relevance"],
|
337
|
+
# Need? to parse <cid:summary cid:final='true' cid:initialAlert='6824288769384' cid:summaryType='Regular'>2</cid:summary>
|
338
|
+
"alert_details" => REXML::XPath.first(element,"./cid:alertDetails").text.tr('\\"', '\''),
|
339
|
+
"risk_rating" => REXML::XPath.first(element,"./cid:riskRatingValue").text,
|
340
|
+
"risk_target" => REXML::XPath.first(element,"./cid:riskRatingValue").attributes["targetValueRating"],
|
341
|
+
"risk_attacker" => REXML::XPath.first(element,"./cid:riskRatingValue").attributes["attackRelevanceRating"],
|
342
|
+
"threat_rating" => REXML::XPath.first(element,"./cid:threatRatingValue").text,
|
343
|
+
"interface" => REXML::XPath.first(element,"./cid:interface").text,
|
344
|
+
"host" => URI.parse(@http["url"]).host,
|
345
|
+
"device" => "IPS",
|
346
|
+
"tags" => "SDEE"
|
347
|
+
}
|
348
|
+
events[eid].merge!({"attacker_port" => REXML::XPath.first(element,"./sd:participants/sd:attacker/sd:port").text}) if REXML::XPath.first(element,"./sd:participants/sd:attacker/sd:port")
|
349
|
+
events[eid].merge!({"target_port" => REXML::XPath.first(element,"./sd:participants/sd:target/sd:port").text}) if REXML::XPath.first(element,"./sd:participants/sd:target/sd:port")
|
350
|
+
events[eid].merge!({"message" => "IdsAlert: '#{events[eid]["description"]}' Attacker: '#{events[eid]["attacker_addr"]}' Target: '#{events[eid]["target_addr"]}' SigId: '#{events[eid]["sig_id"]}'"})
|
351
|
+
end
|
352
|
+
events
|
353
|
+
end
|
354
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'logstash-input-sdee'
|
3
|
+
s.version = '0.6.9'
|
4
|
+
s.date = '2016-08-14'
|
5
|
+
s.summary = "Logstah SDEE input from Cisco ASA"
|
6
|
+
s.description = "This Logstash input plugin allows you to call a Cisco SDEE/CIDEE HTTP API, decode the output of it into event(s), and send them on their merry way."
|
7
|
+
s.authors = ["rootik"]
|
8
|
+
s.email = 'roootik@gmail.com'
|
9
|
+
s.require_paths = ['lib']
|
10
|
+
|
11
|
+
s.files = Dir['lib/**/*', 'examples/**/*', '*.gemspec', 'LICENSE', 'Gemfile', 'README.md', 'CHANGELOG.md', 'CONTRIBUTORS']
|
12
|
+
s.homepage =
|
13
|
+
'http://rubygems.org/gems/logstash-input-sdee'
|
14
|
+
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
|
15
|
+
s.license = 'Apache-2.0'
|
16
|
+
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
|
17
|
+
s.add_runtime_dependency 'logstash-core', '>= 1.4.0', '<= 2.99'
|
18
|
+
s.add_runtime_dependency 'logstash-core-plugin-api', '>= 0.60', '<= 2.99'
|
19
|
+
s.add_runtime_dependency 'logstash-mixin-http_client', '>= 1.0.0', '<= 6.0.0'
|
20
|
+
s.add_runtime_dependency 'rubysl-rexml', '>= 2.0.0', '<= 3.0.0'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logstash-input-sdee
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- rootik
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: logstash-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.0
|
20
|
+
- - <=
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.99'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.4.0
|
30
|
+
- - <=
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.99'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: logstash-core-plugin-api
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.60'
|
40
|
+
- - <=
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '2.99'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.60'
|
50
|
+
- - <=
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2.99'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: logstash-mixin-http_client
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.0.0
|
60
|
+
- - <=
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 6.0.0
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.0.0
|
70
|
+
- - <=
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 6.0.0
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: rubysl-rexml
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 2.0.0
|
80
|
+
- - <=
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.0.0
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.0.0
|
90
|
+
- - <=
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 3.0.0
|
93
|
+
description: This Logstash input plugin allows you to call a Cisco SDEE/CIDEE HTTP
|
94
|
+
API, decode the output of it into event(s), and send them on their merry way.
|
95
|
+
email: roootik@gmail.com
|
96
|
+
executables: []
|
97
|
+
extensions: []
|
98
|
+
extra_rdoc_files: []
|
99
|
+
files:
|
100
|
+
- CHANGELOG.md
|
101
|
+
- CONTRIBUTORS
|
102
|
+
- Gemfile
|
103
|
+
- LICENSE
|
104
|
+
- README.md
|
105
|
+
- examples/patterns/cisco
|
106
|
+
- examples/sdee.conf
|
107
|
+
- lib/logstash/inputs/sdee.rb
|
108
|
+
- logstash-input-sdee.gemspec
|
109
|
+
homepage: http://rubygems.org/gems/logstash-input-sdee
|
110
|
+
licenses:
|
111
|
+
- Apache-2.0
|
112
|
+
metadata:
|
113
|
+
logstash_plugin: 'true'
|
114
|
+
logstash_group: input
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.6.6
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Logstah SDEE input from Cisco ASA
|
135
|
+
test_files: []
|