Initial commit as ossec-ng
This commit is contained in:
commit
03cb22c10f
16 changed files with 2088 additions and 0 deletions
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
*~
|
||||
*#
|
||||
.#*
|
||||
\#*#
|
||||
.*.sw[a-z]
|
||||
*.un~
|
||||
pkg/
|
||||
|
||||
# Berkshelf
|
||||
.vagrant
|
||||
/cookbooks
|
||||
Berksfile.lock
|
||||
|
||||
# Bundler
|
||||
Gemfile.lock
|
||||
bin/*
|
||||
.bundle/*
|
||||
|
||||
.kitchen/
|
||||
.kitchen.local.yml
|
8
Berksfile
Normal file
8
Berksfile
Normal file
|
@ -0,0 +1,8 @@
|
|||
source "https://supermarket.chef.io"
|
||||
|
||||
metadata
|
||||
|
||||
cookbook "selinux_policy", "~> 0.9.5"
|
||||
cookbook "yum-atomic", "~> 0.1.2"
|
||||
cookbook "yum-epel"
|
||||
cookbook "apt-atomic", "~> 0.1.2"
|
691
README.md
Normal file
691
README.md
Normal file
|
@ -0,0 +1,691 @@
|
|||
Description
|
||||
===========
|
||||
Fully automated Installation and configuration of ossec-servers and ossec-agents
|
||||
Manage the key generation and distribution between a server and multiple agents
|
||||
Clean queues on the server if needed (rid)
|
||||
|
||||
Requirements
|
||||
============
|
||||
Any of:
|
||||
* Ubuntu 12.04+
|
||||
* Debian 7.0+
|
||||
* CentOS 6.0+
|
||||
(should work with ossec systems if you have the packages)
|
||||
|
||||
Attributes
|
||||
==========
|
||||
# General Attributes
|
||||
|
||||
The attributes below follow the same namespace syntax that OSSEC does. Refer to
|
||||
the official [OSSEC Documentation](http://www.ossec.net/doc/syntax/ossec_config.html)
|
||||
for more information.
|
||||
|
||||
Default attributes from the cookbook:
|
||||
|
||||
default["ossec"]["version"] = "2.8"
|
||||
default["ossec"]["syslog_output"]["ip"] = "127.0.0.1"
|
||||
default["ossec"]["syslog_output"]["port"] = "514"
|
||||
default["ossec"]["syslog_output"]["min_level"] = "5"
|
||||
default["ossec"]["receiver_port"] = "1514"
|
||||
default["ossec"]["log_alert_level"] = "1"
|
||||
default["ossec"]["email_alert_level"] = "7"
|
||||
default["ossec"]["agents"] = {}
|
||||
|
||||
Default attributes from the ossec-server role:
|
||||
|
||||
"ossec" => {
|
||||
"email_notification" => 'yes',
|
||||
"email_to" => [
|
||||
'ossec@example.net',
|
||||
],
|
||||
"email_from" => 'ossec-server@example.net',
|
||||
"smtp_server" => 'localhost',
|
||||
"white_list" => [
|
||||
'127.0.0.1',
|
||||
'10.1.0.0/16'
|
||||
],
|
||||
"email_alerts" => {
|
||||
'recipient@example.net' => {
|
||||
'level' => '9',
|
||||
'group' => 'syscheck',
|
||||
'event_location_tag' => 'reputation',
|
||||
'event_location_search' => 'roles:*mongodb*',
|
||||
'format' => 'sms',
|
||||
'rule_id' => '100001',
|
||||
'tags' => [
|
||||
'do_not_delay',
|
||||
'do_not_group'
|
||||
]
|
||||
}
|
||||
},
|
||||
"server" => {
|
||||
"service_name" => 'ossec-hids-server'
|
||||
},
|
||||
"syscheck" => {
|
||||
"frequency" => '7200',
|
||||
"alert_new_files" => 'yes',
|
||||
"auto_ignore" => 'no',
|
||||
"directories" => {
|
||||
'/bin' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/sbin' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/usr/bin' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/usr/sbin' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/etc' => {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/tmp' => {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
},
|
||||
"ignore" => {
|
||||
'/etc/openvpn/openvpn-status.log' => {},
|
||||
'/etc/motd' => {},
|
||||
'/etc/mcollective/facts.yaml' => {},
|
||||
'/etc/blkid.tab' => {},
|
||||
'/etc/mtab' => {},
|
||||
'/etc/mail/statistics => {}',
|
||||
'/etc/random-seed' => {},
|
||||
'/etc/adjtime' => {},
|
||||
'/etc/prelink.cache' => {},
|
||||
'/etc/dnscache/stats' => {},
|
||||
'/etc/dnscache/log' => {},
|
||||
'/etc/dnscache2/stats' => {},
|
||||
'/etc/dnscache2/log' => {},
|
||||
'/etc/tinydns/stats' => {},
|
||||
'/etc/tinydns/log' => {}
|
||||
}
|
||||
},
|
||||
"syslog_files" => {
|
||||
'/var/log/syslog' => {},
|
||||
'/var/log/auth.log' => {},
|
||||
'/var/log/daemon.log' => {},
|
||||
'/var/log/kern.log' => {},
|
||||
'/var/log/mail.log' => {},
|
||||
'/var/log/user.log' => {},
|
||||
'/var/log/cron.log' => {}
|
||||
}
|
||||
|
||||
```email_alerts``` is a hash of recipients and servers. Each recipient will
|
||||
receive all of the alert for the listed location (the list is a regex).
|
||||
```event_location_tag``` must contain a valid chef tag. All the nodes listed by
|
||||
that tag will generate a separate ```email_alerts``` rule.
|
||||
This is additional to the default list ```email_to``` and is used to send alert to
|
||||
specific recipients for a limited number of hosts only.
|
||||
|
||||
# Local Rules Definitions
|
||||
Rules are defined in Ruby Hash format and replicate the XML format of regular
|
||||
[OSSEC Rules Syntax](http://www.ossec.net/doc/syntax/head_rules.html)
|
||||
Each rule has a head, a body, tags and info (the last 2 being optional)
|
||||
|
||||
head= <rule id="12345" level="12" frequency="45" timeframe="60">
|
||||
body= <description>Test Rule</description>
|
||||
body= <match>Big Error</match>
|
||||
body= <hostname>server1</hostname>
|
||||
tags= <same_source_ip />
|
||||
tags= <same_source_port />
|
||||
info= <info type="link">http://IjustGotHacked.com</info>
|
||||
</rule>
|
||||
|
||||
The section below are parsed by the template. The following items are mandatory:
|
||||
* head/level
|
||||
* body/description
|
||||
|
||||
```
|
||||
"ossec" =>
|
||||
"rules" => {
|
||||
"100001" => {
|
||||
"head" => {
|
||||
"level" => "7",
|
||||
"maxsize" => "65536",
|
||||
"frequency" => "100",
|
||||
"timeframe" => "3600",
|
||||
"ignore" => "5",
|
||||
"overwrite" => "68321"
|
||||
},
|
||||
"body" => {
|
||||
"hostname_search" => "recipes:mms-agent",
|
||||
"description" => "Super Security Rule for application XYZ",
|
||||
"match" => "super dangerous error happened",
|
||||
"regex" => "^\d+Hello World$",
|
||||
"decoded_as" => "vsftpd",
|
||||
"category" => "windows",
|
||||
"srcip" => "192.168.1.254",
|
||||
"dstip" => "10.1.6.23",
|
||||
"user" => "bob",
|
||||
"program_name" => "nginx",
|
||||
"time" => "09:00-18:00",
|
||||
"weekday" => "monday,tuesday",
|
||||
"id" => "404",
|
||||
"url" => "/changepassword.php",
|
||||
"if_sid" => "100238",
|
||||
"if_group" => "authentication_success",
|
||||
"if_level" => "13",
|
||||
"if_matched_sid" => "12037",
|
||||
"if_matched_group" => "adduser",
|
||||
"if_matched_level" => "7",
|
||||
"options" => "no_email_alert",
|
||||
"check_diff" => "true",
|
||||
"group" => "syscheck"
|
||||
},
|
||||
"tags" => [
|
||||
"same_source_ip",
|
||||
"same_source_port",
|
||||
"same_dst_port",
|
||||
"same_location"
|
||||
],
|
||||
"infos" => {
|
||||
"link" => "http://trac.example.net/ticket/12345",
|
||||
"text" => "the link above contains additional information"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## hostname_search
|
||||
|
||||
To the exception of __hostname_search__, all attributes use the same syntax as the
|
||||
ossec rule in XML format does.
|
||||
__hostname_search__ in this cookbook represents a search query that is executed by
|
||||
the server recipe to populate the ```<hostname>``` with the proper list of hosts,
|
||||
dynamically pulled from chef. Search criterias can be anything that a chef search
|
||||
can take. Example: ```recipe:mongodb\:\:replicaset and tags:reputation```
|
||||
|
||||
# Local Decoders Definitions
|
||||
Decoders are defined in JSON format and replicate the XML format of regular
|
||||
[OSSEC Decoder Syntax](http://www.ossec.net/doc/syntax/head_decoders.html)
|
||||
|
||||
"ossec" => {
|
||||
"decoders" => {
|
||||
'apache-errorlog' => {
|
||||
"program_name" => '^httpd|^apache2',
|
||||
"prematch" => {
|
||||
"parser" => '^\S+ [\w+\s*\d+ \S+ \d+] [\S+] |^[warn] |^[notice] |^[error]'
|
||||
},
|
||||
|
||||
},
|
||||
'apache-errorlog-ip-custom' => {
|
||||
"parent" => 'apache-errorlog',
|
||||
"prematch" => {
|
||||
"offset" => 'after_parent',
|
||||
"parser" => '^[client'
|
||||
},
|
||||
"regex" => {
|
||||
"offset" => 'after_prematch',
|
||||
"parser" => '^ (\d+.\d+.\d+.\d+)]'
|
||||
},
|
||||
"order" => 'srcip'
|
||||
},
|
||||
'web-accesslog-custom' => {
|
||||
"parent" => 'web-accesslog',
|
||||
"type" => 'web-log',
|
||||
"prematch" => {
|
||||
"parser" => '^\d+.\d+.\d+.\d+ |^::ffff:\d+.\d+.\d+.\d+'
|
||||
},
|
||||
"regex" => {
|
||||
"parser" => '^\d+.\d+.\d+.\d+ \S+ (\d+.\d+.\d+.\d+) \S+ \S+ \S+ [\S+ \S\d+] "\w+ (\S+) HTTP\S+ (\d+) \S+ "(\S+)"'
|
||||
},
|
||||
"order" => 'srcip, url, id, extra_data'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```prematch``` and ```regex``` are hashes that can have an ```offset``` value and
|
||||
always have a ```parser``` value. See the ossec documentation for more information.
|
||||
|
||||
# Local Syslog Files and Syscheck Ignore Files
|
||||
If you want specific log files to be monitored on specific agents, you can use
|
||||
a `syslog_files` block in the agent node attributes. The `apply_to`
|
||||
parameter of this block is a `Chef::Search()` that will expand to a list of
|
||||
hosts. If the given agent belong to the list of hosts, it will add the logfile
|
||||
to its local ossec configuration. log_format will default to "syslog" if not set.
|
||||
|
||||
If you want to ignore specific files in syscheck, similarly you can use the same
|
||||
`apply_to` option as shown below:
|
||||
|
||||
```
|
||||
default_attributes(
|
||||
"ossec" => {
|
||||
"syslog_files" => {
|
||||
'/var/log/supervisor/supervisor.log' => {
|
||||
'apply_to' => 'supervisor:*',
|
||||
'log_format' => 'syslog'
|
||||
}
|
||||
},
|
||||
"syscheck" => {
|
||||
"ignore" => {
|
||||
'/etc/openvpn/openvpn-status.log' => {
|
||||
'apply_to' => 'roles:vpn-server'
|
||||
},
|
||||
'^/opt/graphite/storage/' => {
|
||||
'apply_to' => 'roles:graphite-server OR roles:statsd-server',
|
||||
'type' => 'sregex'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
# OSSEC Rules Enable/Disable
|
||||
You can also choose what rules OSSEC it configured to load. Each of the rules in
|
||||
/var/ossec/rules can be enabled and disabled at will with a very simple format.
|
||||
Note that these do not have an apply_to option and are just boolean values, this
|
||||
is because only the OSSEC server loads the rules into action. The following is
|
||||
an example that will enable the normally disabled `symantec-av-rules.xml` and
|
||||
disable the `web_rules.xml`:
|
||||
|
||||
```
|
||||
default_attributes(
|
||||
"ossec" => {
|
||||
"load_rules" => {
|
||||
'symantec-av_rules.xml' => true,
|
||||
'web_rules.xml' => false
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
# Commands and Auto-Response
|
||||
Since OSSEC is an HIDS system, you can also enable and disable commands and
|
||||
active-response functionality and define your own as needed. You can enable
|
||||
or disable existing defined commands and active-responses using the
|
||||
`enable` flag, and target where they are set using the `apply_to` flag. You
|
||||
can also define any of the allowed active-response options dynamically, such
|
||||
as adding agent_id, rules_group, etc.
|
||||
Here is an example of enabling the firewall-stop command and its auto-response
|
||||
and changing it from the default local to all hosts and adding a `rules_group`
|
||||
to the active-response definition so it only triggers on authentication
|
||||
failures:
|
||||
|
||||
```
|
||||
default_attributes(
|
||||
"ossec" => {
|
||||
"command" => {
|
||||
"firewall-stop" => {
|
||||
"enabled" => true
|
||||
}
|
||||
},
|
||||
"auto-response => {
|
||||
"firewall-stop" => {
|
||||
"enabled" => true,
|
||||
"location" => "all",
|
||||
"rules_group" => "authentication_failed,authentication_failures"
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Usage
|
||||
=====
|
||||
* `recipe[ossec-server]` should be a stand alone installation
|
||||
* `recipe[ossec-agent]` should be added (via role[ossec-agent]) to all the nodes of the
|
||||
environment
|
||||
|
||||
# Example Roles
|
||||
## ossec-server
|
||||
This role can be used to provision an ossec server:
|
||||
|
||||
```ruby
|
||||
name 'ossec-server'
|
||||
description 'OSSEC Server'
|
||||
run_list(
|
||||
'recipe[ossec-ng::server]',
|
||||
'role[postfix]'
|
||||
)
|
||||
override_attributes(
|
||||
"ossec" => {
|
||||
"agent" => {
|
||||
"enable" => false
|
||||
}
|
||||
}
|
||||
)
|
||||
default_attributes(
|
||||
"ossec" => {
|
||||
"email_notification" => 'yes',
|
||||
"email_to" => [
|
||||
'ossec-alerts@example.net',
|
||||
],
|
||||
"email_from" => 'ossec-server',
|
||||
"smtp_server" => 'localhost',
|
||||
"white_list" => [
|
||||
'127.0.0.1',
|
||||
'10.0.0.0/0'
|
||||
],
|
||||
"email_alerts" => {
|
||||
'bob@example.net' => {
|
||||
'event_location_tag' => 'project1',
|
||||
},
|
||||
'alice@example.net' => {
|
||||
'event_location_tag' => 'project1',
|
||||
'group' => 'developers',
|
||||
},
|
||||
'eve@example.net' => {
|
||||
'event_location_tag' => 'project2',
|
||||
'group' => 'developers',
|
||||
},
|
||||
'mike@example.net' => {
|
||||
'event_location_search' => 'tags:project1 OR tags:project2 OR tags:project3',
|
||||
'group' => 'developers',
|
||||
},
|
||||
'group2@example.net' => {
|
||||
'event_location_search' => 'roles:application-server AND roles:python-django',
|
||||
'group' => 'frontend-group',
|
||||
},
|
||||
},
|
||||
"decoders" => {
|
||||
1 => {
|
||||
"name" => 'apache-errorlog',
|
||||
"program_name" => '^httpd|^apache2',
|
||||
"prematch" => {
|
||||
"parser" => '^\S+ [\w+\s*\d+ \S+ \d+] [\S+] |^[warn] |^[notice] |^[error]'
|
||||
},
|
||||
|
||||
},
|
||||
2 => {
|
||||
"name" => 'apache-errorlog-ip-custom',
|
||||
"parent" => 'apache-errorlog',
|
||||
"prematch" => {
|
||||
"offset" => 'after_parent',
|
||||
"parser" => '^[client'
|
||||
},
|
||||
"regex" => {
|
||||
"offset" => 'after_prematch',
|
||||
"parser" => '^ (\d+.\d+.\d+.\d+)]'
|
||||
},
|
||||
"order" => 'srcip'
|
||||
},
|
||||
3 => {
|
||||
"name" => 'web-accesslog-custom',
|
||||
"parent" => 'web-accesslog',
|
||||
"type" => 'web-log',
|
||||
"prematch" => {
|
||||
"parser" => '^\d+.\d+.\d+.\d+ |^::ffff:\d+.\d+.\d+.\d+'
|
||||
},
|
||||
"regex" => {
|
||||
"parser" => '^\d+.\d+.\d+.\d+ \S+ (\d+.\d+.\d+.\d+) \S+ \S+ \S+ [\S+ \S\d+] "\w+ (\S+) HTTP\S+ (\d+) \S+ "(\S+)"'
|
||||
},
|
||||
"order" => 'srcip, url, id, extra_data'
|
||||
}
|
||||
},
|
||||
"rules" => {
|
||||
1002 => {
|
||||
"head" => {
|
||||
"level" => '2',
|
||||
"overwrite" => 'yes'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Unknown problem somewhere in the system.',
|
||||
"match" => 'core_dumped|failure|error|Error|attack|bad |illegal |denied|refused|unauthorized|fatal|fail|Segmentation Fault|Corrupted|Traceback|raise',
|
||||
"options" => 'alert_by_email'
|
||||
}
|
||||
},
|
||||
1003 => {
|
||||
"head" => {
|
||||
"level" => '6',
|
||||
"maxsize" => '16384',
|
||||
"overwrite" => 'yes'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Non standard syslog message (larger than 16kB).'
|
||||
}
|
||||
},
|
||||
100003 => {
|
||||
"head" => {
|
||||
"level" => '10'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Successful sudo during non-business hours 6pm to 8am',
|
||||
"if_sid" => '5402,5403',
|
||||
"time" => '10pm - 12am'
|
||||
}
|
||||
},
|
||||
100004 => {
|
||||
"head" => {
|
||||
"level" => '10'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Successful sudo during weekend.',
|
||||
"if_sid" => '5402,5403',
|
||||
"weekday" => 'weekends'
|
||||
}
|
||||
},
|
||||
100005 => {
|
||||
"head" => {
|
||||
"level" => '0'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Silencing sudo errors from accounts allowed to sudo anytime',
|
||||
"if_sid" => '100004,100005',
|
||||
"match" => 'nagios'
|
||||
}
|
||||
},
|
||||
100006 => {
|
||||
"head" => {
|
||||
"level" => '0'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Silencing ossec agent stop/start during business hours 8am to 6pm',
|
||||
"if_sid" => '502,503,504',
|
||||
"time" => '12:00-22:00',
|
||||
"weekday" => 'monday,tuesday,wednesday,thursday,friday'
|
||||
}
|
||||
},
|
||||
100007 => {
|
||||
"head" => {
|
||||
"level" => '8'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Login outside of business hours 6pm to 8am',
|
||||
"if_sid" => '5501',
|
||||
"time" => '22:00-12:00'
|
||||
}
|
||||
},
|
||||
100008 => {
|
||||
"head" => {
|
||||
"level" => '8'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Login during weekend.',
|
||||
"if_sid" => '5501',
|
||||
"weekday" => 'weekends'
|
||||
}
|
||||
},
|
||||
100009 => {
|
||||
"head" => {
|
||||
"level" => '0'
|
||||
},
|
||||
"body" => {
|
||||
"description" => 'Ignore logins alerts for systems accounts',
|
||||
"if_sid" => '100007,100008',
|
||||
"match" => 'ubuntu|nagios'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## ossec-agent
|
||||
This role can be used to provision an ossec-agent
|
||||
|
||||
```ruby
|
||||
name "ossec-agent"
|
||||
description "OSSEC Agent"
|
||||
run_list(
|
||||
"recipe[ossec-ng::agent]"
|
||||
)
|
||||
default_attributes(
|
||||
"ossec" => {
|
||||
"client" => {
|
||||
"service_name" => 'ossec-hids-client'
|
||||
},
|
||||
"syscheck" => {
|
||||
"frequency" => '7200',
|
||||
"alert_new_files" => 'yes',
|
||||
"auto_ignore" => 'no',
|
||||
"directories" => {
|
||||
'/bin' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/boot' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
},
|
||||
'/etc' => {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'no'
|
||||
},
|
||||
'/lib/lsb' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/lib/modules' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/lib/plymouth' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/lib/security' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/lib/terminfo' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/lib/ufw' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/lib/xtables' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
},
|
||||
'/media' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
},
|
||||
'/opt' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
},
|
||||
'/root' => {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'no'
|
||||
},
|
||||
'/srv' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
},
|
||||
'/sbin' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/usr/' => {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'yes'
|
||||
},
|
||||
'/tmp' => {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
},
|
||||
"ignore" => {
|
||||
'/etc/openvpn/openvpn-status.log' => {}
|
||||
'/etc/motd' => {},
|
||||
'/etc/blkid.tab' => {},
|
||||
'/etc/mtab' => {},
|
||||
'/etc/mail/statistics' => {},
|
||||
'/etc/random-seed' => {},
|
||||
'/etc/adjtime' => {},
|
||||
'/etc/prelink.cache' => {},
|
||||
'/root/.bash_history' => {}
|
||||
'^/opt/graphite/storage/' => {
|
||||
'apply_to' => 'roles:graphite-server OR roles:statsd-server',
|
||||
'type' => 'sregex'
|
||||
},
|
||||
'^/usr/lib/elasticsearch' => {
|
||||
'apply_to' => 'roles:elastic-search-cluster',
|
||||
'type' => 'sregex'
|
||||
},
|
||||
'^/etc/chef/cache/checksums/' => {
|
||||
'apply_to' => 'roles:chef-client',
|
||||
'type' => 'sregex'
|
||||
},
|
||||
'^/srv/rsyslog/' => {
|
||||
'apply_to' => 'roles:rsyslog-server',
|
||||
'type' => 'sregex'
|
||||
},
|
||||
'^/etc/djbdns/public-dnscache/supervise/|^/etc/djbdns/tinydns-internal/supervise/|^/etc/djbdns/public-dnscache/log|^/etc/djbdns/tinydns-internal/log|^/etc/djbdns/tinydns-internal/root/data' => {
|
||||
'apply_to' => 'roles:djbdns-server',
|
||||
'type' => 'sregex'
|
||||
}
|
||||
}
|
||||
},
|
||||
"syslog_files" => {
|
||||
'/var/log/syslog' => {},
|
||||
'/var/log/auth.log' => {},
|
||||
'/var/log/daemon.log' => {},
|
||||
'/var/log/kern.log' => {},
|
||||
'/var/log/mail.log' => {},
|
||||
'/var/log/user.log' => {},
|
||||
'/var/log/cron.log' => {},
|
||||
'/var/log/chef/client.log' => {},
|
||||
'/var/log/supervisor/supervisor.log' => {
|
||||
'apply_to' => 'supervisor:*',
|
||||
'log_format' => 'syslog'
|
||||
},
|
||||
'/var/log/rabbitmq/rabbit1.log' => {
|
||||
'apply_to' => 'recipes:rabbitmq',
|
||||
'log_format' => 'multi-line:3'
|
||||
},
|
||||
'/var/log/nginx/access.log' => {
|
||||
'apply_to' => 'nginx:*',
|
||||
'log_format' => 'syslog'
|
||||
},
|
||||
'/var/log/nginx/error.log' => {
|
||||
'apply_to' => 'nginx:*',
|
||||
'log_format' => 'syslog'
|
||||
},
|
||||
'/var/log/nagios3/nagios.log' => {
|
||||
'apply_to' => 'roles:nagios-server',
|
||||
'log_format' => 'syslog'
|
||||
},
|
||||
'/var/log/nagios3/apache_access.log' => {
|
||||
'apply_to' => 'roles:nagios-server',
|
||||
'log_format' => 'syslog'
|
||||
},
|
||||
'/var/log/nagios3/apache_error.log' => {
|
||||
'apply_to' => 'roles:nagios-server',
|
||||
'log_format' => 'syslog'
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Author
|
||||
======
|
||||
Eric Renfro - psi-jack@linux-help.org - https://linux-help.org
|
||||
|
||||
Derived from works from:
|
||||
Julien Vehent - julien@linuxwall.info - http://jve.linuxwall.info
|
||||
|
267
attributes/ossec.rb
Normal file
267
attributes/ossec.rb
Normal file
|
@ -0,0 +1,267 @@
|
|||
default["ossec"]["version"] = "2.8"
|
||||
default["ossec"]["syslog_output"]["ip"] = "172.16.254.254"
|
||||
default["ossec"]["syslog_output"]["port"] = "514"
|
||||
default["ossec"]["syslog_output"]["min_level"] = "5"
|
||||
default["ossec"]["receiver_port"] = "1514"
|
||||
default["ossec"]["log_alert_level"] = "1"
|
||||
default["ossec"]["email_alert_level"] = "7"
|
||||
default["ossec"]["email_maxperhour"] = "9999"
|
||||
default["ossec"]["memory_size"] = "100000"
|
||||
default["ossec"]["remote"]["connection"] = "secure"
|
||||
default["ossec"]["agents"] = {}
|
||||
default["ossec"]["rules"] = {}
|
||||
default["ossec"]["email_alerts"] = {}
|
||||
if node["roles"].include?("ossec-server")
|
||||
default["ossec"]["agent"]["enable"] = false
|
||||
else
|
||||
default["ossec"]["agent"]["enable"] = true
|
||||
end
|
||||
|
||||
if platform_family?('debian')
|
||||
default["ossec"]["server"]["service_name"] = "ossec-hids-server"
|
||||
default["ossec"]["client"]["service_name"] = "ossec-hids-client"
|
||||
elsif platform_family?('rhel')
|
||||
default["ossec"]["server"]["service_name"] = "ossec-hids"
|
||||
default["ossec"]["client"]["service_name"] = "ossec-hids"
|
||||
end
|
||||
|
||||
# Sane defaults for each distribution platform for syslog files
|
||||
if platform_family?('debian')
|
||||
default["ossec"]["syslog_files"]["/var/log/auth.log"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/daemon.log"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/kern.log"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/mail.log"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/syslog"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/user.log"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/chef/client.log"] = {}
|
||||
|
||||
elsif platform_family?('rhel')
|
||||
default["ossec"]["syslog_files"]["/var/log/cron"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/dmesg"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/maillog"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/messages"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/secure"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/spooler"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/yum.log"] = {}
|
||||
default["ossec"]["syslog_files"]["/var/log/chef/client.log"] = {}
|
||||
end
|
||||
|
||||
# Sane defaults for syscheck
|
||||
default["ossec"]["syscheck"]["frequency"] = '7200'
|
||||
default["ossec"]["syscheck"]["alert_new_files"] = 'yes'
|
||||
default["ossec"]["syscheck"]["auto_ignore"] = 'no'
|
||||
|
||||
default["ossec"]["syscheck"]["directories"]['/bin'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/boot'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/etc'] = {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/lib/lsb'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/lib/modules'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/lib/plymouth'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/lib/security'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/lib/terminfo'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/lib/ufw'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/lib/xtables'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/media'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/opt'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/root'] = {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/srv'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/sbin'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/usr/'] = {
|
||||
'report_changes' => 'yes',
|
||||
'realtime' => 'yes'
|
||||
}
|
||||
default["ossec"]["syscheck"]["directories"]['/tmp'] = {
|
||||
'report_changes' => 'no',
|
||||
'realtime' => 'no'
|
||||
}
|
||||
|
||||
# Syscheck Ignore Files
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/openvpn/openvpn-status.log'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/motd'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/blkid.tab'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/mtab'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/mail/statistics'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/random-seed'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/adjtime'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/prelink.cache'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/root/.bash_history'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/root/.viminfo'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/dnscache/stats'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/dnscache/log'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/dnscache2/stats'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/dnscache2/log'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/tinydns/stats'] = {}
|
||||
default["ossec"]["syscheck"]["ignore"]['/etc/tinydns/log'] = {}
|
||||
|
||||
# Commands
|
||||
default["ossec"]["command"]["host-deny"]["enabled"] = false
|
||||
default["ossec"]["command"]["host-deny"]["executable"] = 'host-deny.sh'
|
||||
default["ossec"]["command"]["host-deny"]["expect"] = 'srcip'
|
||||
default["ossec"]["command"]["host-deny"]["timeout_allowed"] = 'yes'
|
||||
|
||||
default["ossec"]["command"]["firewall-stop"]["enabled"] = true
|
||||
default["ossec"]["command"]["firewall-stop"]["executable"] = 'firewall-drop.sh'
|
||||
default["ossec"]["command"]["firewall-stop"]["expect"] = 'srcip'
|
||||
default["ossec"]["command"]["firewall-stop"]["timeout_allowed"] = 'yes'
|
||||
|
||||
default["ossec"]["command"]["disable-account"]["enabled"] = false
|
||||
default["ossec"]["command"]["disable-account"]["executable"] = 'disable-account.sh'
|
||||
default["ossec"]["command"]["disable-account"]["expect"] = 'user'
|
||||
default["ossec"]["command"]["disable-account"]["timeout_allowed"] = 'yes'
|
||||
|
||||
default["ossec"]["local_command"] = {}
|
||||
|
||||
# Active-Responses
|
||||
default["ossec"]["active-response"]["host-deny"]["enabled"] = true
|
||||
default["ossec"]["active-response"]["host-deny"]["location"] = 'local'
|
||||
default["ossec"]["active-response"]["host-deny"]["level"] = '10'
|
||||
default["ossec"]["active-response"]["host-deny"]["timeout"] = '600'
|
||||
|
||||
default["ossec"]["active-response"]["firewall-stop"]["enabled"] = true
|
||||
default["ossec"]["active-response"]["firewall-stop"]["location"] = 'local'
|
||||
default["ossec"]["active-response"]["firewall-stop"]["level"] = '10'
|
||||
default["ossec"]["active-response"]["firewall-stop"]["timeout"] = '600'
|
||||
|
||||
default["ossec"]["active-response"]["disable-account"]["enabled"] = false
|
||||
default["ossec"]["active-response"]["disable-account"]["location"] = 'local'
|
||||
default["ossec"]["active-response"]["disable-account"]["level"] = '10'
|
||||
default["ossec"]["active-response"]["disable-account"]["timeout"] = '600'
|
||||
|
||||
|
||||
# internal options, you probably don't want to touch that
|
||||
default["ossec"]["internal"]["analysisd"]["default_timeframe"] = "360"
|
||||
default["ossec"]["internal"]["analysisd"]["stats_maxdiff"] = "25000"
|
||||
default["ossec"]["internal"]["analysisd"]["stats_mindiff"] = "250"
|
||||
default["ossec"]["internal"]["analysisd"]["stats_percent_diff"] = "30"
|
||||
default["ossec"]["internal"]["analysisd"]["fts_list_size"] = "32"
|
||||
default["ossec"]["internal"]["analysisd"]["fts_min_size_for_str"] = "14"
|
||||
default["ossec"]["internal"]["analysisd"]["log_fw"] = "1"
|
||||
default["ossec"]["internal"]["logcollector"]["loop_timeout"] = "2"
|
||||
default["ossec"]["internal"]["logcollector"]["open_attempts"] = "8"
|
||||
default["ossec"]["internal"]["logcollector"]["remote_commands"] = 1
|
||||
default["ossec"]["internal"]["remoted"]["recv_counter_flush"] = "128"
|
||||
default["ossec"]["internal"]["remoted"]["comp_average_printout"] = "19999"
|
||||
default["ossec"]["internal"]["remoted"]["verify_msg_id"] = "1"
|
||||
default["ossec"]["internal"]["maild"]["strict_checking"] = "1"
|
||||
default["ossec"]["internal"]["maild"]["groupping"] = "0"
|
||||
default["ossec"]["internal"]["maild"]["full_subject"] = "1"
|
||||
default["ossec"]["internal"]["maild"]["geoip"] = "1"
|
||||
default["ossec"]["internal"]["monitord"]["compress"] = "1"
|
||||
default["ossec"]["internal"]["monitord"]["sign"] = "1"
|
||||
default["ossec"]["internal"]["monitord"]["monitor_agents"] = "1"
|
||||
default["ossec"]["internal"]["syscheck"]["sleep"] = "2"
|
||||
default["ossec"]["internal"]["syscheck"]["sleep_after"] = "15"
|
||||
default["ossec"]["internal"]["dbd"]["reconnect_attempts"] = "10"
|
||||
default["ossec"]["internal"]["window"]["debug"] = "0"
|
||||
default["ossec"]["internal"]["syscheck"]["debug"] = "0"
|
||||
default["ossec"]["internal"]["remoted"]["debug"] = "0"
|
||||
default["ossec"]["internal"]["analysisd"]["debug"] = "0"
|
||||
default["ossec"]["internal"]["logcollector"]["debug"] = "0"
|
||||
default["ossec"]["internal"]["agent"]["debug"] = "0"
|
||||
|
||||
# What OSSEC fules files to load
|
||||
default["ossec"]["load_rules"] = {
|
||||
'rules_config.xml' => true,
|
||||
'pam_rules.xml' => true,
|
||||
'sshd_rules.xml' => true,
|
||||
'telnetd_rules.xml' => false,
|
||||
'syslog_rules.xml' => true,
|
||||
'arpwatch_rules.xml' => true,
|
||||
'symantec-av_rules.xml' => false,
|
||||
'symantec-ws_rules.xml' => false,
|
||||
'pix_rules.xml' => false,
|
||||
'named_rules.xml' => true,
|
||||
'smbd_rules.xml' => true,
|
||||
'vsftpd_rules.xml' => false,
|
||||
'pure-ftpd_rules.xml' => false,
|
||||
'proftpd_rules.xml' => false,
|
||||
'ms_ftpd_rules.xml' => false,
|
||||
'ftpd_rules.xml' => false,
|
||||
'hordeimp_rules.xml' => false,
|
||||
'roundcube_rules.xml' => false,
|
||||
'wordpress_rules.xml' => false,
|
||||
'cimserver_rules.xml' => false,
|
||||
'vpopmail_rules.xml' => false,
|
||||
'vmpop3d_rules.xml' => false,
|
||||
'courier_rules.xml' => false,
|
||||
'web_rules.xml' => true,
|
||||
'web_appsec_rules.xml' => true,
|
||||
'apache_rules.xml' => true,
|
||||
'nginx_rules.xml' => true,
|
||||
'php_rules.xml' => true,
|
||||
'mysql_rules.xml' => true,
|
||||
'postgresql_rules.xml' => true,
|
||||
'ids_rules.xml' => true,
|
||||
'squid_rules.xml' => false,
|
||||
'firewall_rules.xml' => true,
|
||||
'cisco-ios_rules.xml' => false,
|
||||
'netscreenfw_rules.xml' => false,
|
||||
'sonicwall_rules.xml' => false,
|
||||
'postfix_rules.xml' => true,
|
||||
'sendmail_rules.xml' => false,
|
||||
'imapd_rules.xml' => false,
|
||||
'mailscanner_rules.xml' => false,
|
||||
'dovecot_rules.xml' => false,
|
||||
'ms-exchange_rules.xml' => false,
|
||||
'racoon_rules.xml' => false,
|
||||
'vpn_concentrator_rules.xml' => false,
|
||||
'spamd_rules.xml' => false,
|
||||
'msauth_rules.xml' => false,
|
||||
'clam_av_rules.xml' => true,
|
||||
'mcafee_av_rules.xml' => false,
|
||||
'trend-osce_rules.xml' => false,
|
||||
'ms-se_rules.xml' => false,
|
||||
'zeus_rules.xml' => false,
|
||||
'solaris_bsm_rules.xml' => false,
|
||||
'vmware_rules.xml' => false,
|
||||
'ms_dhcp_rules.xml' => false,
|
||||
'asterisk_rules.xml' => false,
|
||||
'ossec_rules.xml' => true,
|
||||
'attack_rules.xml' => true,
|
||||
'local_rules.xml' => true,
|
||||
}
|
266
libraries/core.rb
Normal file
266
libraries/core.rb
Normal file
|
@ -0,0 +1,266 @@
|
|||
# Core function for OSSEC
|
||||
# Used by the server and agent recipes
|
||||
|
||||
module OssecCore
|
||||
|
||||
def ossec_hostname_search()
|
||||
# resolve the hostname_search of a rule to a list of hosts
|
||||
node["ossec"]["rules"].each do |id,params|
|
||||
if not params.nil?
|
||||
params[:body].each do |key, value|
|
||||
if key.eql?('hostname_search')
|
||||
hosts_list = search(:node,
|
||||
"(#{value}) AND roles:ossec-agent "\
|
||||
" AND chef_environment:#{node.chef_environment}"
|
||||
).map {|n| n.hostname}
|
||||
if hosts_list.empty?
|
||||
# search didn't return anything
|
||||
# store a dummy value in the attributes
|
||||
Chef::Log.info("OSSEC: Hostname search returned empty result. " +
|
||||
"'#{value}'")
|
||||
params[:body][:hostname] = "invalid-search-returned-empty-result"
|
||||
else
|
||||
# store in the node params but discard the last char
|
||||
params[:body][:hostname] = hosts_list.join('|')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def ossec_event_location_search()
|
||||
# resolve the location search of an email_alert block to a hostname
|
||||
node["ossec"]["email_alerts"].each do|recipient,params|
|
||||
if params.has_key?('event_location_search')
|
||||
if Chef::Config[:solo]
|
||||
Chef::Log.warn('This recipe uses search. Chef Solo does not support search.')
|
||||
else
|
||||
dest = search(:node,
|
||||
"(#{params[:event_location_search]}) " \
|
||||
"AND chef_environment:#{node.chef_environment}"
|
||||
).map {|n| n.hostname}
|
||||
node.default["ossec"]["email_alerts"][recipient]["resolved_search"] = dest
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def ossec_set_syscheck_flags!(*args)
|
||||
# go through the list of command/active-response and check the ones
|
||||
# that apply to this node
|
||||
args.each do |config|
|
||||
unless node["ossec"]["syscheck"][config].nil?
|
||||
node["ossec"]["syscheck"][config].each do |item, params|
|
||||
unless params[:apply_to].nil?
|
||||
locations = search(:node,
|
||||
"(#{params[:apply_to]}) " \
|
||||
"AND chef_environment:#{node.chef_environment}"
|
||||
).map {|n| n.ipaddress}
|
||||
if locations.include?(node["ipaddress"])
|
||||
node.default["ossec"]["syscheck"][config][item]["use_here"] = true
|
||||
else
|
||||
node.default["ossec"]["syscheck"][config][item]["use_here"] = false
|
||||
end
|
||||
else
|
||||
node.default["ossec"]["syscheck"][config][item]["use_here"] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def ossec_set_filtered_flags!(*args)
|
||||
# go through the list of command/active-response and check the ones
|
||||
# that apply to this node
|
||||
args.each do |config|
|
||||
unless node["ossec"][config].nil?
|
||||
node["ossec"][config].each do |item, params|
|
||||
unless params[:apply_to].nil?
|
||||
locations = search(:node,
|
||||
"(#{params[:apply_to]}) " \
|
||||
"AND chef_environment:#{node.chef_environment}"
|
||||
).map {|n| n.ipaddress}
|
||||
if locations.include?(node["ipaddress"])
|
||||
node.default["ossec"][config][item]["use_here"] = true
|
||||
else
|
||||
node.default["ossec"][config][item]["use_here"] = false
|
||||
end
|
||||
else
|
||||
node.default["ossec"][config][item]["use_here"] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def ossec_agent_create_parameters(agent, server)
|
||||
# Returns a hash with the identiers for this agent
|
||||
agent_hash = {}
|
||||
# IP is defined by lanip, if available (ohai plugin network_addr)
|
||||
# or by the default ipaddress otherwise
|
||||
agent_hash[:ip] = agent[:network][:lanip] || agent.ipaddress
|
||||
|
||||
# Ossec limits the agents name length to 32 characters, so to avoid
|
||||
# names collisions, we concatenate the agent_ip with the first characters
|
||||
# of the hostname
|
||||
name = agent_hash[:ip] + "_" + agent[:hostname]
|
||||
agent_hash[:name] = name[0,31]
|
||||
|
||||
# ossec agent id is an integer used to identify an agent. we force that ID
|
||||
# to be the IP address without the dots (10.1.2.3 becomes 10123)
|
||||
agent_hash[:id] = agent_hash[:ip].gsub(".", "")
|
||||
|
||||
agent_hash[:key] = "undef"
|
||||
if server["ossec"]["agents"].has_key?(agent_hash[:id])
|
||||
if server["ossec"]["agents"][agent_hash[:id]].has_key?('key')
|
||||
agent_hash[:key] = server["ossec"]["agents"][agent_hash[:id]]["key"]
|
||||
end
|
||||
end
|
||||
agent_hash[:rid] = "none"
|
||||
|
||||
return agent_hash
|
||||
end
|
||||
|
||||
|
||||
def ossec_generate_agent_key(agent_hash)
|
||||
# Returns a 64 characters double md5 hash, used as a symetric key
|
||||
seed1 = rand(100000000000).to_s
|
||||
seed2 = rand(100000000000).to_s
|
||||
str1 = Digest::MD5.hexdigest(seed1 + \
|
||||
agent_hash[:id] + \
|
||||
agent_hash[:ip] + \
|
||||
seed2)
|
||||
str2 = Digest::MD5.hexdigest(seed2 + \
|
||||
agent_hash[:name] + \
|
||||
seed1 + \
|
||||
agent_hash[:ip] + \
|
||||
agent_hash[:id])
|
||||
key = str1 + str2
|
||||
return key
|
||||
end
|
||||
|
||||
|
||||
def ossec_agent_has_valid_key?(agent_hash, server)
|
||||
# Does the server have a valid key for this agent ?
|
||||
if server["ossec"]["agents"].key?(agent_hash[:id])
|
||||
if server["ossec"]["agents"][agent_hash[:id]].key?('key')
|
||||
if server["ossec"]["agents"][agent_hash[:id]]["key"].length == 64
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def ossec_agent_knows_key?(agent_hash, agent)
|
||||
# Does the agent have a key that matches the server ?
|
||||
if agent.key?('ossec')
|
||||
if agent["ossec"].key?('agents')
|
||||
if agent["ossec"]["agents"].key?(agent_hash[:id])
|
||||
if agent["ossec"]["agents"][agent_hash[:id]].key?('key')
|
||||
if agent["ossec"]["agents"][agent_hash[:id]]["key"] == agent_hash[:key]
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def ossec_verify_agent(agent_hash, server)
|
||||
# check if this agent (id, name, ip) is defined on the server
|
||||
if server["ossec"]["agents"].key?(agent_hash[:id])
|
||||
agent_srv_data = server["ossec"]["agents"][agent_hash[:id]]
|
||||
if agent_srv_data[:name].eql?(agent_hash[:name])
|
||||
if agent_srv_data[:ip].eql?(agent_hash[:ip])
|
||||
return true
|
||||
else
|
||||
Chef::Log.info("OSSEC: agent ip mismatch. " +
|
||||
"server has '#{agent_srv_data[:ip]}' " +
|
||||
"agent has '#{agent_hash[:ip]}'")
|
||||
end
|
||||
else
|
||||
Chef::Log.info("OSSEC: agent name mismatch. " +
|
||||
"server has '#{agent_srv_data[:name]}' " +
|
||||
"agent has '#{agent_hash[:name]}'")
|
||||
end
|
||||
else
|
||||
Chef::Log.info("OSSEC: agent name '#{agent_hash[:name]}' " +
|
||||
" ip '#{agent_hash[:ip]}'" +
|
||||
" configuration not found on server.")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def ossec_agent_is_active?(id)
|
||||
if File.exists?("/var/ossec/bin/agent_control")
|
||||
#cmd = Chef::ShellOut.new("/var/ossec/bin/agent_control -s -i #{id}")
|
||||
cmd = Mixlib::ShellOut.new("/var/ossec/bin/agent_control -s -i #{id}")
|
||||
cmd_ret = cmd.run_command
|
||||
status = cmd.stdout.split(",")
|
||||
if status[3] && status[3].eql?("Active")
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def ossec_agent_is_zombie?(id)
|
||||
if File.exists?("/var/ossec/bin/agent_control")
|
||||
#cmd = Chef::ShellOut.new("/var/ossec/bin/agent_control -s -i #{id}")
|
||||
cmd = Mixlib::ShellOut.new("/var/ossec/bin/agent_control -s -i #{id}")
|
||||
cmd_ret = cmd.run_command
|
||||
status = cmd.stdout.split(",")
|
||||
if not status[6] || status[3] =~ /(Never connected|)/
|
||||
return true
|
||||
elsif status[6] !~ /Unknown/
|
||||
last_keep_alive = Time.parse(status[6])
|
||||
three_days_ago = (Time.now - (24*60*60*3))
|
||||
if three_days_ago > last_keep_alive
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def ossec_agent_should_be_removed?(id)
|
||||
if File.exists?("/var/ossec/bin/agent_control")
|
||||
#cmd = Chef::ShellOut.new("/var/ossec/bin/agent_control -s -i #{id}")
|
||||
cmd = Mixlib::ShellOut.new("/var/ossec/bin/agent_control -s -i #{id}")
|
||||
cmd_ret = cmd.run_command
|
||||
status = cmd.stdout.split(",")
|
||||
if not status[6] or status[6] =~ /Unknown/
|
||||
return true
|
||||
else
|
||||
last_keep_alive = Time.parse(status[6])
|
||||
seven_days_ago = (Time.now - (24*60*60*7))
|
||||
if seven_days_ago > last_keep_alive
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def ossec_agent_needs_rid?(id, agent)
|
||||
# Check if the agent queue needs to be removed, either because the server
|
||||
# said so, or because the agent asked for it
|
||||
if agent["ossec"]["agents"][id]["rid"].eql?("todo") \
|
||||
or node["ossec"]["agents"][id]["rid"].eql?("todo")
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
33
metadata.rb
Normal file
33
metadata.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
name "ossec-ng"
|
||||
maintainer "Eric Renfro"
|
||||
maintainer_email "psi-jack@linux-help.org"
|
||||
license "GPLv2"
|
||||
description "Installs/Configures ossec"
|
||||
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
||||
version "1.2.0"
|
||||
issues_url "http://git.linux-help.org/Linux-Help/ossec-ng/issues"
|
||||
source_url "http://git.linux-help.org/Linux-Help/ossec-ng"
|
||||
|
||||
recipe 'ossec-ng::default', 'Installs the neccessary repositories to install OSSEC'
|
||||
recipe 'ossec-ng::server', 'Installs OSSEC for use as a server'
|
||||
recipe 'ossec-ng::agent', 'Installs OSSEC for use as an agent'
|
||||
|
||||
%w(
|
||||
debian
|
||||
ubuntu
|
||||
centos
|
||||
redhat
|
||||
scientific
|
||||
amazon
|
||||
oracle
|
||||
).each do |os|
|
||||
supports os
|
||||
end
|
||||
|
||||
depends 'yum-epel'
|
||||
depends 'yum-atomic', '~> 0.1.2'
|
||||
depends 'apt-atomic', '~> 0.1.2'
|
||||
|
||||
suggests 'postfix'
|
||||
suggests 'selinux_policy'
|
||||
|
116
recipes/agent.rb
Normal file
116
recipes/agent.rb
Normal file
|
@ -0,0 +1,116 @@
|
|||
# Ossec Agent provisioning recipe
|
||||
# install the ossec-hids-client package, push the global
|
||||
# and role specific configuration for the node
|
||||
# get a key from the ossec-server if there's one
|
||||
|
||||
#if not node['lsb']['codename'].eql?('lucid')
|
||||
# return true
|
||||
#end
|
||||
|
||||
include_recipe "yum-atomic"
|
||||
|
||||
class Chef::Recipe
|
||||
include OssecCore
|
||||
end
|
||||
|
||||
|
||||
# Run this recipe if the node is an agent. Since the ossec::agent recipe is
|
||||
# added to the base role, ossec-servers will run it as well, making this check
|
||||
# necessary
|
||||
if not node["ossec"]["agent"]["enable"]
|
||||
# return will exit this recipe
|
||||
# and continue the chef provisioning
|
||||
Chef::Log.info("OSSEC: agent is not enabled on this node")
|
||||
return true
|
||||
end
|
||||
|
||||
# Search for the ossec server, and do nothing if there's none
|
||||
ossec_server = search(:node,
|
||||
"role:ossec-server " \
|
||||
"AND chef_environment:#{node.chef_environment}"
|
||||
).first
|
||||
if ossec_server.nil?
|
||||
Chef::Log.info("OSSEC: No ossec server available. Agent will not be provisionned")
|
||||
return true
|
||||
end
|
||||
|
||||
# install the agent package
|
||||
package "ossec-hids-client"
|
||||
|
||||
# define the agent parameters
|
||||
agent_hash = ossec_agent_create_parameters(node, ossec_server)
|
||||
|
||||
# check for the agent configuration on the server. if the server has none, do
|
||||
# not continue the provisioning. If the server has a configuration for this
|
||||
# agent, store the parameters on the node and continue
|
||||
if ossec_verify_agent(agent_hash, ossec_server)
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]] = ossec_server["ossec"]["agents"][agent_hash[:id]].to_hash
|
||||
else
|
||||
Chef::Log.info("OSSEC: this agent is unknown on the ossec server")
|
||||
return true
|
||||
end
|
||||
|
||||
# Make sure that the server prepared a key for us
|
||||
unless ossec_agent_has_valid_key?(agent_hash, ossec_server)
|
||||
Chef::Log.info("OSSEC: Server doesn't have a valid key for agent.")
|
||||
return true
|
||||
end
|
||||
|
||||
service "ossec-agent" do
|
||||
#provider Chef::Provider::Service::Init
|
||||
service_name node["ossec"]["client"]["service_name"]
|
||||
supports :start => true, :stop => true, :restart => true, :status => true
|
||||
action [ :start ]
|
||||
only_if "test -e /var/ossec/etc/ossec.conf && test -e /var/ossec/etc/client.keys"
|
||||
end
|
||||
|
||||
# Get the IP of the ossec server
|
||||
ossec_server_ip = ossec_server[:network][:lanip] || ossec_server.ipaddress
|
||||
|
||||
# Expand the local flags from node attributes
|
||||
ossec_set_filtered_flags!("command", "active-response", "syslog_files")
|
||||
ossec_set_syscheck_flags!("ignore")
|
||||
|
||||
template "/var/ossec/etc/ossec.conf" do
|
||||
source "ossec-agent.conf.erb"
|
||||
owner "ossec"
|
||||
group "ossec"
|
||||
variables("ossec_server_ip" => ossec_server_ip )
|
||||
manage_symlink_source true
|
||||
notifies :restart, "service[ossec-agent]"
|
||||
end
|
||||
|
||||
# If client.keys is modified, ask for a queue rid on the server
|
||||
template "/var/ossec/etc/client.keys" do
|
||||
mode 0440
|
||||
owner "root"
|
||||
group "ossec"
|
||||
notifies :create, "ruby_block[set-rid-flag]"
|
||||
notifies :restart, "service[ossec-agent]"
|
||||
end
|
||||
|
||||
# "set-rid-flag" is not run by default, but called when the agent's key
|
||||
# is modified (or created)
|
||||
ruby_block "set-rid-flag" do
|
||||
block do
|
||||
# if the server side rid flag is not set to "done",
|
||||
# request a queue rid by setting the agent side flag to "todo"
|
||||
if ossec_server["ossec"]["agents"][agent_hash[:id]]["rid"].eql?("none")
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]]["rid"] = "todo"
|
||||
Chef::Log.info "Setting Queue Rid Flag on"
|
||||
end
|
||||
end
|
||||
action :nothing
|
||||
end
|
||||
|
||||
# unset rid flag if necessary, check that at every run
|
||||
if node["ossec"]["agents"][agent_hash[:id]]["rid"].eql?("todo") \
|
||||
and ossec_server["ossec"]["agents"][agent_hash[:id]]["rid"].eql?("done")
|
||||
ruby_block "unset rid flag" do
|
||||
block do
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]]["rid"] = "none"
|
||||
Chef::Log.info "Setting Queue Rid Flag off"
|
||||
end
|
||||
notifies :restart, "service[ossec-agent]"
|
||||
end
|
||||
end
|
6
recipes/default.rb
Normal file
6
recipes/default.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Cookbook Name:: ossec
|
||||
# Recipe:: default
|
||||
#
|
||||
include_recipe "ossec::agent"
|
||||
|
181
recipes/server.rb
Normal file
181
recipes/server.rb
Normal file
|
@ -0,0 +1,181 @@
|
|||
# Ossec server provisioning recipe
|
||||
# install the ossec-hids-server package and push the
|
||||
# default configuration from the templates
|
||||
|
||||
include_recipe "yum-atomic"
|
||||
|
||||
class Chef::Recipe
|
||||
include OssecCore
|
||||
end
|
||||
|
||||
|
||||
package "ossec-hids-server"
|
||||
|
||||
# Get all the agents at once, more efficient
|
||||
if Chef::Config[:solo]
|
||||
Chef::Log.warn('This recipe uses search. Chef Solo does not support search')
|
||||
else
|
||||
ossec_agents = search(:node,
|
||||
"roles:ossec-agent "\
|
||||
"AND chef_environment:#{node.chef_environment}")
|
||||
|
||||
# set local command/active-response flags
|
||||
ossec_set_filtered_flags!("command", "active-response", "syslog_files")
|
||||
ossec_set_syscheck_flags!("ignore")
|
||||
|
||||
# resolve searches in server rules
|
||||
ossec_hostname_search()
|
||||
|
||||
# resolve email_alerts location searches
|
||||
ossec_event_location_search()
|
||||
|
||||
# initialize the agent hash on the first run
|
||||
if node["ossec"]["agents"].nil?
|
||||
node.normal["ossec"]["agents"] = {}
|
||||
end
|
||||
|
||||
ossec_agents.each do |agent|
|
||||
# don't process thy self
|
||||
if agent["ipaddress"] == node["ipaddress"]
|
||||
next
|
||||
end
|
||||
|
||||
agent_hash = ossec_agent_create_parameters(agent, node)
|
||||
|
||||
# this agent is running fine, go to the next one
|
||||
if ossec_agent_is_active?(agent_hash[:id])
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]]["status"] = "active"
|
||||
next
|
||||
end
|
||||
|
||||
# check that the agent ID still point to the same IP and hostname
|
||||
# otherwise, delete the record from the ossec server
|
||||
if not ossec_verify_agent(agent_hash, node)
|
||||
Chef::Log.info("OSSEC: deleting server record for agent '#{agent_hash[:id]}'")
|
||||
node.normal["ossec"]["agents"].delete(agent_hash[:id])
|
||||
end
|
||||
|
||||
# if this agent doesn't have a valid key, generate one
|
||||
if not ossec_agent_has_valid_key?(agent_hash, node)
|
||||
Chef::Log.info("OSSEC: agent '#{agent_hash[:id]}' needs a key. Generating one.")
|
||||
agent_hash[:key] = ossec_generate_agent_key(agent_hash)
|
||||
agent_hash[:rid] = "todo"
|
||||
agent_hash[:status] = "key_exists"
|
||||
end
|
||||
|
||||
# save agent parameters
|
||||
agent_hash.each do |k,v|
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]][k] = v
|
||||
end
|
||||
|
||||
# Don't continue if the agent has a valid key but doesn't know it yet
|
||||
if not ossec_agent_knows_key?(agent_hash, agent)
|
||||
Chef::Log.info("OSSEC: agent '#{agent_hash[:id]}' didn't pick up its key yet.")
|
||||
next
|
||||
end
|
||||
|
||||
# Check if it needs a queue cleanup
|
||||
if ossec_agent_needs_rid?(agent_hash[:id], agent)
|
||||
ruby_block "ossec queue rid" do
|
||||
block do
|
||||
if File.exists?("/var/ossec/queue/rids/#{agent_hash[:id]}")
|
||||
File.delete("/var/ossec/queue/rids/#{agent_hash[:id]}")
|
||||
Chef::Log.info("OSSEC: deleted queue for agent '#{agent_hash[:id]}'")
|
||||
else
|
||||
Chef::Log.info("OSSEC: No queue for agent '#{agent_hash[:id]}.'")
|
||||
end
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]]["rid"] = "done"
|
||||
end
|
||||
notifies :restart, "service[ossec-server]", :delayed
|
||||
end
|
||||
# done with this agent, go to the next one
|
||||
next
|
||||
end
|
||||
|
||||
# If after all that, the agent is still not active, mark it as so
|
||||
if not ossec_agent_is_active?(agent_hash[:id])
|
||||
if ossec_agent_is_zombie?(agent_hash[:id])
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]]["status"] = "zombie"
|
||||
# if the agent is a zombie, perform a rid of its queue on the next run
|
||||
Chef::Log.info("OSSEC: agent #{agent_hash[:id]} is a zombie. " +
|
||||
"Request queue deletion")
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]]["rid"] = "todo"
|
||||
else
|
||||
node.normal["ossec"]["agents"][agent_hash[:id]]["status"] = "disconnected"
|
||||
Chef::Log.info("OSSEC: agent #{agent_hash[:id]} connection failed. " +
|
||||
"Performing restart")
|
||||
#cmd = Chef::ShellOut.new("/var/ossec/bin/agent_control -R #{agent_hash[:id]}")
|
||||
cmd = Mixlib::ShellOut.new("/var/ossec/bin/agent_control -R #{agent_hash[:id]}")
|
||||
cmd_ret = cmd.run_command
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Remove the attributes of an agent from the ossec server if the agent doesn't
|
||||
# exist on Chef and the last keep_alive is more than 7 days old
|
||||
node["ossec"]["agents"].each do |agent_id, params|
|
||||
if params[:status].eql?('key_exists')
|
||||
next
|
||||
end
|
||||
|
||||
agent = ossec_agents.select{ |n| (n[:ossec][:agents].has_key?(agent_id) \
|
||||
&& n[:ossec][:agent][:enable])
|
||||
}.first
|
||||
|
||||
if not agent.nil?
|
||||
next
|
||||
end
|
||||
if ossec_agent_should_be_removed?(agent_id)
|
||||
Chef::Log.info("OSSEC: Removing old agent '#{agent_id}' - '#{params[:name]}'")
|
||||
node["ossec"]["agents"].delete(agent_id)
|
||||
else
|
||||
Chef::Log.info("OSSEC: agent '#{agent_id}' - '#{params[:name]}' is candidate for removal")
|
||||
node.normal["ossec"]["agents"][agent_id]["status"] = 'candidate_for_removal'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
template "/var/ossec/etc/client.keys" do
|
||||
mode '0440'
|
||||
owner "root"
|
||||
group "ossec"
|
||||
end
|
||||
|
||||
template "/var/ossec/rules/local_rules.xml" do
|
||||
owner "root"
|
||||
group "root"
|
||||
notifies :restart, "service[ossec-server]", :delayed
|
||||
end
|
||||
|
||||
template "/var/ossec/etc/local_decoder.xml" do
|
||||
owner "root"
|
||||
group "root"
|
||||
notifies :restart, "service[ossec-server]", :delayed
|
||||
end
|
||||
|
||||
template "/var/ossec/etc/ossec.conf" do
|
||||
source "ossec-server.conf.erb"
|
||||
owner "ossec"
|
||||
group "ossec"
|
||||
manage_symlink_source true
|
||||
variables(
|
||||
:ossec_agents => ossec_agents
|
||||
)
|
||||
notifies :restart, "service[ossec-server]", :delayed
|
||||
end
|
||||
|
||||
template "/var/ossec/etc/internal_options.conf" do
|
||||
mode "0444"
|
||||
owner "root"
|
||||
group "root"
|
||||
notifies :restart, "service[ossec-server]", :delayed
|
||||
end
|
||||
|
||||
service "ossec-server" do
|
||||
#provider Chef::Provider::Service::Init
|
||||
service_name node["ossec"]["server"]["service_name"]
|
||||
supports :start => true, :stop => true, :restart => true, :status => true
|
||||
action [ :start ]
|
||||
only_if { File.exist?("/var/ossec/etc/ossec.conf") }
|
||||
end
|
||||
|
36
recipes/supervisor_logs.rb
Normal file
36
recipes/supervisor_logs.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# This recipe will list the log file created by supervisor
|
||||
# and add the necessary attributes to have those monitored
|
||||
# by the local ossec-agent
|
||||
|
||||
# cleanup, before recreation
|
||||
node["ossec"]["local_syslog_files"].each do |logfile, params|
|
||||
if logfile =~ /supervisor/
|
||||
node["ossec"]["local_syslog_files"].delete(logfile)
|
||||
end
|
||||
end
|
||||
|
||||
# each program run by supervisor has a set of logfiles
|
||||
node["supervisor"]["programs"].each do |program_name, config|
|
||||
total_procs = config["numprocs"] || 1
|
||||
# each process of a program has its own log file
|
||||
0.upto(total_procs.to_i - 1) do |numproc|
|
||||
logfile = "#{node["supervisor"]["log_path"]}/#{program_name}_#{numproc}_stdout.log"
|
||||
# add the stdout supervisor log file
|
||||
node.normal["ossec"]["local_syslog_files"][logfile] = {
|
||||
'apply_to' => "fqdn:#{node['fqdn']}",
|
||||
'log_format' => 'syslog',
|
||||
'use_here' => 'true'
|
||||
}
|
||||
log("Ossec::Supervisor: Adding '#{logfile}' to monitored log files")
|
||||
|
||||
logfile = "#{node["supervisor"]["log_path"]}/#{program_name}_#{numproc}_stderr.log"
|
||||
# add the stderr supervisor log file
|
||||
node.normal["ossec"]["local_syslog_files"][logfile] = {
|
||||
'apply_to' => "fqdn:#{node['fqdn']}",
|
||||
'log_format' => 'syslog',
|
||||
'use_here' => 'true'
|
||||
}
|
||||
log("Ossec::Supervisor: Adding '#{logfile}' to monitored log files")
|
||||
|
||||
end
|
||||
end
|
7
templates/default/client.keys.erb
Normal file
7
templates/default/client.keys.erb
Normal file
|
@ -0,0 +1,7 @@
|
|||
<% if not node["ossec"]["agents"].nil?
|
||||
node["ossec"]["agents"].sort.each do |ip,fields|
|
||||
if not fields[:key].nil? %>
|
||||
<%= fields[:id] %> <%= fields[:name] %> <%= fields[:ip] %> <%= fields[:key] %>
|
||||
<% end
|
||||
end
|
||||
end -%>
|
115
templates/default/internal_options.conf.erb
Normal file
115
templates/default/internal_options.conf.erb
Normal file
|
@ -0,0 +1,115 @@
|
|||
# internal_options.conf, Daniel B. Cid (dcid @ ossec.net).
|
||||
#
|
||||
# DO NOT TOUCH THIS FILE. The default configuration
|
||||
# is at ossec.conf. More information at:
|
||||
# http://www.ossec.net/en/manual.html
|
||||
#
|
||||
# This file should be handled with care. It contain
|
||||
# run time modifications that can affect the use
|
||||
# of ossec. Only change it if you know what you
|
||||
# are doing. Again, look first at ossec.conf
|
||||
# for most of the things you want to change.
|
||||
|
||||
|
||||
# Analysisd default rule timeframe.
|
||||
analysisd.default_timeframe=<%= node["ossec"]["internal"]["analysisd"]["default_timeframe"] %>
|
||||
# Analysisd stats maximum diff.
|
||||
analysisd.stats_maxdiff=<%= node["ossec"]["internal"]["analysisd"]["stats_maxdiff"] %>
|
||||
# Analysisd stats minimum diff.
|
||||
analysisd.stats_mindiff=<%= node["ossec"]["internal"]["analysisd"]["stats_mindiff"] %>
|
||||
# Analysisd stats percentage (how much to differ from average)
|
||||
analysisd.stats_percent_diff=<%= node["ossec"]["internal"]["analysisd"]["stats_percent_diff"] %>
|
||||
# Analysisd FTS list size.
|
||||
analysisd.fts_list_size=<%= node["ossec"]["internal"]["analysisd"]["fts_list_size"] %>
|
||||
# Analysisd FTS minimum string size.
|
||||
analysisd.fts_min_size_for_str=<%= node["ossec"]["internal"]["analysisd"]["fts_min_size_for_str"] %>
|
||||
# Analysisd Enable the firewall log (at logs/firewall/firewall.log)
|
||||
# 1 to enable, 0 to disable.
|
||||
analysisd.log_fw=<%= node["ossec"]["internal"]["analysisd"]["log_fw"] %>
|
||||
|
||||
|
||||
# Logcollector file loop timeout (check every 2 seconds for file changes)
|
||||
logcollector.loop_timeout=<%= node["ossec"]["internal"]["logcollector"]["loop_timeout"] %>
|
||||
|
||||
# Logcollector number of attempts to open a log file.
|
||||
logcollector.open_attempts=<%= node["ossec"]["internal"]["logcollector"]["open_attempts"] %>
|
||||
|
||||
# Logcollector: Allow the agents to run commands as defined in agent.conf
|
||||
logcollector.remote_commands=<%= node["ossec"]["internal"]["logcollector"]["remote_commands"] %>
|
||||
|
||||
|
||||
# Remoted counter io flush.
|
||||
remoted.recv_counter_flush=<%= node["ossec"]["internal"]["remoted"]["recv_counter_flush"] %>
|
||||
|
||||
# Remoted compression averages printout.
|
||||
remoted.comp_average_printout=<%= node["ossec"]["internal"]["remoted"]["comp_average_printout"] %>
|
||||
|
||||
# Verify msg id (set to 0 to disable it)
|
||||
remoted.verify_msg_id=<%= node["ossec"]["internal"]["remoted"]["verify_msg_id"] %>
|
||||
|
||||
|
||||
# Maild strict checking (0=disabled, 1=enabled)
|
||||
maild.strict_checking=<%= node["ossec"]["internal"]["maild"]["strict_checking"] %>
|
||||
|
||||
# Maild grouping (0=disabled, 1=enabled)
|
||||
# Groups alerts within the same e-mail.
|
||||
maild.groupping=<%= node["ossec"]["internal"]["maild"]["groupping"] %>
|
||||
|
||||
# Maild full subject (0=disabled, 1=enabled)
|
||||
maild.full_subject=<%= node["ossec"]["internal"]["maild"]["full_subject"] %>
|
||||
|
||||
# Maild GeoIP support
|
||||
maild.geoip=<%= node["ossec"]["internal"]["maild"]["geoip"] %>
|
||||
|
||||
|
||||
# Monitord day_wait. Ammount of seconds to wait before compressing/signing
|
||||
# the files.
|
||||
monitord.day_wait=10<%= node["ossec"]["internal"]["monitord"]["day_wait"] %>
|
||||
|
||||
# Monitord compress. (0=do not compress, 1=compress)
|
||||
monitord.compress=<%= node["ossec"]["internal"]["monitord"]["compress"] %>
|
||||
|
||||
# Monitord sign. (0=do not sign, 1=sign)
|
||||
monitord.sign=<%= node["ossec"]["internal"]["monitord"]["sign"] %>
|
||||
|
||||
# Monitord monitor_agents. (0=do not monitor, 1=monitor)
|
||||
monitord.monitor_agents=<%= node["ossec"]["internal"]["monitord"]["monitor_agents"] %>
|
||||
|
||||
|
||||
# Syscheck checking/usage speed. To avoid large cpu/memory
|
||||
# usage, you can specify how much to sleep after generating
|
||||
# the checksum of X files. The default is to sleep 2 seconds
|
||||
# after reading 15 files.
|
||||
syscheck.sleep=<%= node["ossec"]["internal"]["syscheck"]["sleep"] %>
|
||||
syscheck.sleep_after=<%= node["ossec"]["internal"]["syscheck"]["sleep_after"] %>
|
||||
|
||||
|
||||
# Database - maximum number of reconnect attempts
|
||||
dbd.reconnect_attempts=<%= node["ossec"]["internal"]["dbd"]["reconnect_attempts"] %>
|
||||
|
||||
|
||||
# Debug options.
|
||||
# Debug 0 -> no debug
|
||||
# Debug 1 -> first level of debug
|
||||
# Debug 2 -> full debugging
|
||||
|
||||
# Windows debug (used by the windows agent)
|
||||
windows.debug=<%= node["ossec"]["internal"]["window"]["debug"] %>
|
||||
|
||||
# Syscheck (local, server and unix agent)
|
||||
syscheck.debug=<%= node["ossec"]["internal"]["syscheck"]["debug"] %>
|
||||
|
||||
# Remoted (server debug)
|
||||
remoted.debug=<%= node["ossec"]["internal"]["remoted"]["debug"] %>
|
||||
|
||||
# Analysisd (server or local)
|
||||
analysisd.debug=<%= node["ossec"]["internal"]["analysisd"]["debug"] %>
|
||||
|
||||
# Log collector (server, local or unix agent)
|
||||
logcollector.debug=<%= node["ossec"]["internal"]["logcollector"]["debug"] %>
|
||||
|
||||
# Unix agentd
|
||||
agent.debug=<%= node["ossec"]["internal"]["agent"]["debug"] %>
|
||||
|
||||
|
||||
# EOF
|
21
templates/default/local_decoder.xml.erb
Normal file
21
templates/default/local_decoder.xml.erb
Normal file
|
@ -0,0 +1,21 @@
|
|||
<% node["ossec"]["decoders"].sort_by{|k,v| k.to_i}.each do |id,params|
|
||||
if not params.nil? -%>
|
||||
<decoder name="<%= params[:name] %>">
|
||||
<% params.sort.each do |key, value|
|
||||
unless key.eql?('name')
|
||||
if params[key].is_a?(Hash)
|
||||
if key.eql?('prematch') or key.eql?('regex')
|
||||
if params[key].has_key?('offset') -%>
|
||||
<<%= key %> offset="<%= params[key][:offset] %>"><%= params[key][:parser] %></<%= key %>>
|
||||
<% else -%>
|
||||
<<%= key %>><%= params[key][:parser] %></<%= key %>>
|
||||
<% end
|
||||
end
|
||||
else -%>
|
||||
<<%= key %>><%= value %></<%= key %>>
|
||||
<% end
|
||||
end
|
||||
end -%>
|
||||
</decoder>
|
||||
<% end
|
||||
end -%>
|
30
templates/default/local_rules.xml.erb
Normal file
30
templates/default/local_rules.xml.erb
Normal file
|
@ -0,0 +1,30 @@
|
|||
<group name="local,syslog,">
|
||||
<% node["ossec"]["rules"].sort_by{|k,v| k.to_i}.each do |id,params|
|
||||
headers = ""
|
||||
if params.has_key?('head')
|
||||
params[:head].sort.each do |key, value|
|
||||
headers += " " + key + "=\"" + value + "\""
|
||||
end
|
||||
end -%>
|
||||
<rule id="<%= id %>" <%= headers %>>
|
||||
<% if params.has_key?('body')
|
||||
params[:body].sort.each do |key, value|
|
||||
if not key.eql?('hostname_search') -%>
|
||||
<<%= key %>><%= value %></<%= key %>>
|
||||
<%
|
||||
end
|
||||
end
|
||||
end
|
||||
if params.has_key?('tags')
|
||||
params[:tags].sort.each do |tag| -%>
|
||||
<<%= tag %> />
|
||||
<% end
|
||||
end
|
||||
if params.has_key?('info')
|
||||
params[:info].sort.each do |key, value| -%>
|
||||
<info type="<%= key %>"><%= value %></info>
|
||||
<% end
|
||||
end -%>
|
||||
</rule>
|
||||
<% end -%>
|
||||
</group>
|
91
templates/default/ossec-agent.conf.erb
Normal file
91
templates/default/ossec-agent.conf.erb
Normal file
|
@ -0,0 +1,91 @@
|
|||
<!-- OSSEC Agent configuration from chef ossec cookbook v.<%= node["ossec"]["version"] %> -->
|
||||
<ossec_config>
|
||||
<client>
|
||||
<server-ip><%= @ossec_server_ip %></server-ip>
|
||||
</client>
|
||||
|
||||
<syscheck>
|
||||
<!-- Frequency that syscheck is executed -- default every 2 hours -->
|
||||
<frequency><%= node["ossec"]["syscheck"]["frequency"] %></frequency>
|
||||
|
||||
<!-- Directories to check (perform all possible verifications) -->
|
||||
<% node["ossec"]["syscheck"]["directories"].sort_by {|k,v| k}.each do |directory,params| -%>
|
||||
<directories check_all="yes" report_changes="<%= params[:report_changes] %>" realtime="<%= params[:realtime] %>"><%= directory %></directories>
|
||||
<% end -%>
|
||||
|
||||
<alert_new_files><%= node["ossec"]["syscheck"]["alert_new_files"] %></alert_new_files>
|
||||
<auto_ignore><%= node["ossec"]["syscheck"]["auto_ignore"] %></auto_ignore>
|
||||
|
||||
<!-- Files/directories to ignore -->
|
||||
<% unless node["ossec"]["syscheck"]["ignore"].nil?
|
||||
node["ossec"]["syscheck"]["ignore"].sort_by {|k,v|}.each do |path,params|
|
||||
if params["use_here"] == true
|
||||
type = params["type"] || "simple"
|
||||
if type == "simple" -%>
|
||||
<ignore><%= path %></ignore>
|
||||
<% else -%>
|
||||
<ignore type='sregex'><%= path %></ignore>
|
||||
<% end
|
||||
end
|
||||
end
|
||||
end -%>
|
||||
</syscheck>
|
||||
|
||||
<rootcheck>
|
||||
<rootkit_files>/var/ossec/etc/shared/rootkit_files.txt</rootkit_files>
|
||||
<rootkit_trojans>/var/ossec/etc/shared/rootkit_trojans.txt</rootkit_trojans>
|
||||
</rootcheck>
|
||||
|
||||
<!-- Commands and Active-Responses -->
|
||||
<% node["ossec"]["command"].each_pair do |command, params|
|
||||
if params["enabled"] == true && \
|
||||
params["use_here"] == true -%>
|
||||
<command>
|
||||
<name><%= command %></name>
|
||||
<% params.each_pair do |param, value|
|
||||
unless (param == 'enabled' || \
|
||||
param == 'apply_to' || \
|
||||
param == 'use_here') -%>
|
||||
<<%= param %>><%= value %></<%= param %>>
|
||||
<% end
|
||||
end -%>
|
||||
</command>
|
||||
<% end
|
||||
end %>
|
||||
|
||||
<% node["ossec"]["active-response"].each_pair do |command, params|
|
||||
if params["enabled"] == true && \
|
||||
params["use_here"] == true && \
|
||||
(node["ossec"]["command"][command]["enabled"] == true &&
|
||||
node["ossec"]["command"][command]["use_here"] == true) -%>
|
||||
<active-response>
|
||||
<command><%= command %></command>
|
||||
<% params.each_pair do |param, value|
|
||||
unless (param == 'enabled' || \
|
||||
param == 'apply_to' || \
|
||||
param == 'use_here') -%>
|
||||
<<%= param %>><%= value %></<%= param %>>
|
||||
<% end
|
||||
end -%>
|
||||
</active-response>
|
||||
<% end
|
||||
end -%>
|
||||
|
||||
<!-- Files to monitor (localfiles) -->
|
||||
<% node["ossec"]["syslog_files"].sort_by {|k,v| k}.each do |logfile,params|
|
||||
if params["use_here"] == true
|
||||
log_format = params["log_format"] || "syslog" -%>
|
||||
<localfile>
|
||||
<log_format><%= log_format %></log_format>
|
||||
<location><%= logfile %></location>
|
||||
<% params.each_pair do |param,value|
|
||||
unless(param == 'log_format' || \
|
||||
param == 'apply_to' ||
|
||||
param == 'use_here') -%>
|
||||
<<%= param %>><%= value %></<%= param %>>
|
||||
<% end
|
||||
end -%>
|
||||
</localfile>
|
||||
<% end
|
||||
end -%>
|
||||
</ossec_config>
|
200
templates/default/ossec-server.conf.erb
Normal file
200
templates/default/ossec-server.conf.erb
Normal file
|
@ -0,0 +1,200 @@
|
|||
<!-- OSSEC Server configuration from chef ossec cookbook v.<%= node["ossec"]["version"] %> -->
|
||||
<ossec_config>
|
||||
<global>
|
||||
<email_notification><%= node["ossec"]["email_notification"] %></email_notification>
|
||||
<% node["ossec"]["email_to"].sort_by {|k| k}.each do |recipient| -%>
|
||||
<email_to><%= recipient %></email_to>
|
||||
<% end -%>
|
||||
<smtp_server><%= node["ossec"]["smtp_server"] %></smtp_server>
|
||||
<email_from><%= node["ossec"]["email_from"]%></email_from>
|
||||
<email_maxperhour><%=node["ossec"]["email_maxperhour"]%></email_maxperhour>
|
||||
<memory_size><%=node["ossec"]["memory_size"]%></memory_size>
|
||||
<% node["ossec"]["white_list"].sort_by {|k| k}.each do |ip| -%>
|
||||
<white_list><%= ip %></white_list>
|
||||
<% end -%>
|
||||
</global>
|
||||
|
||||
<rules>
|
||||
<% node["ossec"]["load_rules"].each_pair do |name, value|
|
||||
if value -%>
|
||||
<include><%= name %></include>
|
||||
<% end
|
||||
end -%>
|
||||
</rules>
|
||||
|
||||
<remote>
|
||||
<connection><%= node["ossec"]["remote"]["connection"] %></connection>
|
||||
<local_ip><%= node.ipaddress %></local_ip>
|
||||
</remote>
|
||||
|
||||
<syslog_output>
|
||||
<server><%= node["ossec"]["syslog_output"]["ip"] %></server>
|
||||
<port><%= node["ossec"]["syslog_output"]["port"] %></port>
|
||||
<level><%= node["ossec"]["syslog_output"]["min_level"] %></level>
|
||||
</syslog_output>
|
||||
|
||||
<alerts>
|
||||
<log_alert_level><%= node["ossec"]["log_alert_level"] %></log_alert_level>
|
||||
<email_alert_level><%= node["ossec"]["email_alert_level"] %></email_alert_level>
|
||||
</alerts>
|
||||
|
||||
<reports>
|
||||
<category>authentication_success</category>
|
||||
<user type="relation">srcip</user>
|
||||
<title>Daily report: Successful logins</title>
|
||||
<% node["ossec"]["email_to"].sort_by {|k| k}.each do |recipient| -%>
|
||||
<email_to><%= recipient %></email_to>
|
||||
<% end -%>
|
||||
</reports>
|
||||
|
||||
<reports>
|
||||
<category>web</category>
|
||||
<title>Daily report: Web</title>
|
||||
<% node["ossec"]["email_to"].sort_by {|k| k}.each do |recipient| -%>
|
||||
<email_to><%= recipient %></email_to>
|
||||
<% end -%>
|
||||
</reports>
|
||||
|
||||
<reports>
|
||||
<title>Daily report: Level 7</title>
|
||||
<level>7</level>
|
||||
<srcip type="relation">level</srcip>
|
||||
<% node["ossec"]["email_to"].sort_by {|k| k}.each do |recipient| -%>
|
||||
<email_to><%= recipient %></email_to>
|
||||
<% end -%>
|
||||
</reports>
|
||||
|
||||
<reports>
|
||||
<title>Daily report: Level 12</title>
|
||||
<level>12</level>
|
||||
<srcip type="relation">level</srcip>
|
||||
<% node["ossec"]["email_to"].sort_by {|k| k}.each do |recipient| -%>
|
||||
<email_to><%= recipient %></email_to>
|
||||
<% end -%>
|
||||
</reports>
|
||||
|
||||
<reports>
|
||||
<category>syscheck</category>
|
||||
<title>Daily report: File changes</title>
|
||||
<location type="relation">filename</location>
|
||||
<% node["ossec"]["email_to"].sort_by {|k| k}.each do |recipient| -%>
|
||||
<email_to><%= recipient %></email_to>
|
||||
<% end -%>
|
||||
</reports>
|
||||
|
||||
<% node["ossec"]["email_alerts"].sort_by {|k,v| k}.each do |recipient,params|
|
||||
locations = []
|
||||
if params.has_key?('event_location_tag')
|
||||
locations = @ossec_agents.select{
|
||||
|n| n[:tags].include?(
|
||||
params[:event_location_tag]
|
||||
)
|
||||
}.map {|n2| n2.network.lanip || '172.172.172.172'}
|
||||
elsif params.has_key?('resolved_search')
|
||||
locations = params[:resolved_search]
|
||||
end
|
||||
locations.sort_by {|k| k}.each do |location| -%>
|
||||
<email_alerts>
|
||||
<email_to><%= recipient %></email_to>
|
||||
<event_location><%= location %></event_location>
|
||||
<% params.sort_by {|k,v| k}.each do |key, value|
|
||||
unless key =~ /event_location_tag|event_location_search|resolved_search/
|
||||
if key.eql?('tags')
|
||||
value.sort_by {|k| k}.each do |tag| -%>
|
||||
<<%= tag %> />
|
||||
<% end
|
||||
else -%>
|
||||
<<%= key %>><%= value %></<%= key %>>
|
||||
<% end
|
||||
end
|
||||
end -%>
|
||||
</email_alerts>
|
||||
<% end
|
||||
end -%>
|
||||
|
||||
<syscheck>
|
||||
<!-- Frequency that syscheck is executed -- default every 2 hours -->
|
||||
<frequency><%= node["ossec"]["syscheck"]["frequency"] %></frequency>
|
||||
|
||||
<!-- Directories to check (perform all possible verifications) -->
|
||||
<% node["ossec"]["syscheck"]["directories"].sort_by {|k,v| k}.each do |directory,params| -%>
|
||||
<directories check_all="yes" report_changes="<%= params[:report_changes] %>" realtime="<%= params[:realtime] %>"><%= directory %></directories>
|
||||
<% end -%>
|
||||
|
||||
<alert_new_files><%= node["ossec"]["syscheck"]["alert_new_files"] %></alert_new_files>
|
||||
<auto_ignore><%= node["ossec"]["syscheck"]["auto_ignore"] %></auto_ignore>
|
||||
|
||||
<!-- Files/directories to ignore -->
|
||||
<% unless node["ossec"]["syscheck"]["ignore"].nil?
|
||||
node["ossec"]["syscheck"]["ignore"].sort_by {|k,v|}.each do |path,params|
|
||||
if params["use_here"] == true
|
||||
type = params["type"] || "simple"
|
||||
if type == "simple" -%>
|
||||
<ignore><%= path %></ignore>
|
||||
<% else -%>
|
||||
<ignore type='sregex'><%= path %></ignore>
|
||||
<% end
|
||||
end
|
||||
end
|
||||
end -%>
|
||||
</syscheck>
|
||||
|
||||
|
||||
<rootcheck>
|
||||
<rootkit_files>/var/ossec/etc/shared/rootkit_files.txt</rootkit_files>
|
||||
<rootkit_trojans>/var/ossec/etc/shared/rootkit_trojans.txt</rootkit_trojans>
|
||||
</rootcheck>
|
||||
|
||||
<!-- Commands and Active-Responses -->
|
||||
<% node["ossec"]["command"].each_pair do |command, params|
|
||||
if params["enabled"] == true && \
|
||||
params["use_here"] == true -%>
|
||||
<command>
|
||||
<name><%= command %></name>
|
||||
<% params.each_pair do |param, value|
|
||||
unless (param == 'enabled' || \
|
||||
param == 'apply_to' || \
|
||||
param == 'use_here') -%>
|
||||
<<%= param %>><%= value %></<%= param %>>
|
||||
<% end
|
||||
end -%>
|
||||
</command>
|
||||
<% end
|
||||
end %>
|
||||
|
||||
<% node["ossec"]["active-response"].each_pair do |command, params|
|
||||
if params["enabled"] == true && \
|
||||
params["use_here"] == true && \
|
||||
(node["ossec"]["command"][command]["enabled"] == true &&
|
||||
node["ossec"]["command"][command]["use_here"] == true) -%>
|
||||
<active-response>
|
||||
<command><%= command %></command>
|
||||
<% params.each_pair do |param, value|
|
||||
unless (param == 'enabled' || \
|
||||
param == 'apply_to' || \
|
||||
param == 'use_here') -%>
|
||||
<<%= param %>><%= value %></<%= param %>>
|
||||
<% end
|
||||
end -%>
|
||||
</active-response>
|
||||
<% end
|
||||
end -%>
|
||||
|
||||
<!-- Files to monitor (localfiles) -->
|
||||
<% node["ossec"]["syslog_files"].sort_by {|k,v| k}.each do |logfile,params|
|
||||
if params["use_here"] == true
|
||||
log_format = params["log_format"] || "syslog" -%>
|
||||
<localfile>
|
||||
<log_format><%= log_format %></log_format>
|
||||
<location><%= logfile %></location>
|
||||
<% params.each_pair do |param,value|
|
||||
unless(param == 'log_format' || \
|
||||
param == 'apply_to' ||
|
||||
param == 'use_here') -%>
|
||||
<<%= param %>><%= value %></<%= param %>>
|
||||
<% end
|
||||
end -%>
|
||||
</localfile>
|
||||
<% end
|
||||
end -%>
|
||||
</ossec_config>
|
Loading…
Reference in a new issue