diff --git a/.kitchen.do.local.yml b/.kitchen.do.yml similarity index 100% rename from .kitchen.do.local.yml rename to .kitchen.do.yml diff --git a/.kitchen.dokken.yml b/.kitchen.dokken.yml new file mode 100644 index 00000000..9b1eef4b --- /dev/null +++ b/.kitchen.dokken.yml @@ -0,0 +1,79 @@ +# this file is used for configuration of kitchen dokken +# for integration tests in the CI +--- +driver: + name: dokken + privileged: true # because Docker and SystemD/Upstart +<% if ENV['CHEF_VERSION'] %> + chef_version: <%= ENV['CHEF_VERSION'] %> +<% end %> + +transport: + name: dokken + +provisioner: + name: dokken + +verifier: + name: inspec + sudo: true + +platforms: +- name: ubuntu-14-04 + driver: + image: ubuntu:14.04 +- name: ubuntu-16-04 + driver: + image: ubuntu:16.04 + intermediate_instructions: + - RUN /usr/bin/apt-get update + pid_one_command: /bin/systemd +- name: centos-6 + driver: + image: centos:6 + intermediate_instructions: + - RUN yum install -y initscripts +- name: centos-7 + driver: + image: centos:7 + pid_one_command: /usr/lib/systemd/systemd +- name: oracle-6 + driver: + image: oraclelinux:6 +- name: oracle-7 + driver: + image: oraclelinux:7 + pid_one_command: /usr/lib/systemd/systemd +- name: debian-7 + driver: + image: debian:7 + intermediate_instructions: + - RUN /usr/bin/apt-get update + - RUN /usr/bin/apt-get install -y procps +- name: debian-8 + driver: + image: debian:8 + intermediate_instructions: + - RUN /usr/bin/apt-get update + - RUN /usr/bin/apt-get install -y procps + pid_one_command: /bin/systemd +- name: fedora-26 + driver: + image: fedora:26 + pid_one_command: /usr/lib/systemd/systemd + intermediate_instructions: + - RUN dnf install -y yum +- name: fedora-27 + driver: + image: fedora:27 + pid_one_command: /usr/lib/systemd/systemd + intermediate_instructions: + - RUN dnf install -y yum +- name: opensuse-42 + driver: + image: opensuse:leap + pid_one_command: /usr/lib/systemd/systemd +- name: amazonlinux-2 + driver: + image: dokken/amazonlinux-2 + pid_one_command: /usr/lib/systemd/systemd diff --git a/.kitchen.yml b/.kitchen.yml index 4562d216..5b35b1ed 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -37,7 +37,7 @@ platforms: - name: opensuse-leap-42 driver_config: box: bento/opensuse-leap-42.1 -- name: amzn2 +- name: amazonlinux-2 driver_config: box: stakahashi/amazonlinux2 diff --git a/.travis.yml b/.travis.yml index 4fe38ffb..879c1546 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,42 +1,54 @@ --- -sudo: false +sudo: required language: ruby bundler_args: "--without development" dist: trusty cache: bundler +services: +- docker + rvm: 2.4.1 before_install: - gem update --system # see https://github.com/bundler/bundler/issues/5357 env: - - INSTANCE=ubuntu-14-04 - - INSTANCE=ubuntu-16-04 - - INSTANCE=ubuntu-16-04 CHEF_VERSION=12.14.60 - - INSTANCE=centos-6 - - INSTANCE=centos-7 - - INSTANCE=centos-7 CHEF_VERSION=12.14.60 - - INSTANCE=debian-7 - - INSTANCE=debian-8 - - INSTANCE=fedora-26 - - INSTANCE=fedora-27 + - INSTANCE=ubuntu-14-04 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=ubuntu-16-04 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=ubuntu-16-04 CHEF_VERSION=12.14.60 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=centos-6 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=centos-7 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=centos-7 CHEF_VERSION=12.14.60 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=debian-7 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=debian-8 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=fedora-26 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=fedora-27 KITCHEN_LOCAL_YAML=.kitchen.do.yml + - INSTANCE=ubuntu-14-04 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=ubuntu-16-04 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=ubuntu-16-04 CHEF_VERSION=12.14.60 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=centos-6 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=centos-7 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=centos-7 CHEF_VERSION=12.14.60 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=oracle-6 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=oracle-7 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=debian-7 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=debian-8 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=fedora-26 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=fedora-27 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=opensuse-42 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - INSTANCE=amazonlinux-2 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml script: - - bundle exec rake prepare_do_env kitchen KITCHEN_LOCAL_YAML=.kitchen.do.local.yml + - bundle exec rake kitchen matrix: - allow_failures: # allow failues of integration tests as the forks might miss the DO token - - env: INSTANCE=ubuntu-14-04 - - env: INSTANCE=ubuntu-16-04 - - env: INSTANCE=ubuntu-16-04 CHEF_VERSION=12.14.60 - - env: INSTANCE=centos-6 - - env: INSTANCE=centos-7 - - env: INSTANCE=centos-7 CHEF_VERSION=12.14.60 - - env: INSTANCE=debian-7 - - env: INSTANCE=debian-8 - - env: INSTANCE=fedora-26 - - env: INSTANCE=fedora-27 + allow_failures: # temporaray disable failing tests until all problems are fixed + - env: INSTANCE=ubuntu-16-04 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - env: INSTANCE=ubuntu-16-04 CHEF_VERSION=12.14.60 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - env: INSTANCE=centos-7 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - env: INSTANCE=centos-7 CHEF_VERSION=12.14.60 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml + - env: INSTANCE=opensuse-42 KITCHEN_LOCAL_YAML=.kitchen.dokken.yml include: - env: UNIT_AND_LINT=1 script: diff --git a/Gemfile b/Gemfile index 465c54ea..16e92a31 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,8 @@ end group :integration do gem 'kitchen-digitalocean' - gem 'kitchen-inspec' + gem 'kitchen-dokken' + gem 'kitchen-inspec', '>= 0.23.1' gem 'kitchen-vagrant' gem 'test-kitchen', '~> 1.0' end diff --git a/README.md b/README.md index 0acc116b..2fc939a1 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ It will not: ## Attributes +* `['os-hardening']['components'][COMPONENT_NAME]` - allows the fine control over which components should be executed via default recipe. See below for more details * `['os-hardening']['desktop']['enable'] = false` true if this is a desktop system, ie Xorg, KDE/GNOME/Unity/etc * `['os-hardening']['network']['forwarding'] = false` @@ -104,6 +105,22 @@ It will not: * `['os-hardening']['security']['selinux_mode'] = 'unmanaged'` set to `unmanaged` if you want to let selinux configuration as it is. Set to `enforcing` to enforce or `permissive` to permissive SELinux. +### Controlling the included components + +`default.rb` includes other components based on the ohai autodetection attributes of your system. E.g. do not execute selinux on non-RHEL systems. You can override this behavior and force components to be executed or not via setting attributes in `node['os-hardening']['components']` on the override level. Example + +```ruby +# some attribute file +# do not include sysctl and auditd +override['os-hardening']['components']['sysctl'] = false +override['os-hardening']['components']['auditd'] = false + +# force selinux to be included +override['os-hardening']['components']['selinux'] = true +``` + +In the current implementation different components are located in the different recipes. See the available recipes or `default.rb` for possible component names. + ## Usage Add the recipes to the `run_list`, it should be last: @@ -149,11 +166,12 @@ $ kitchen test ### CI testing of forks -You can enable testing of your fork in [Travis CI](http://travis-ci.org/). By default you will get linting and spec tests. +You can enable testing of your fork in [Travis CI](http://travis-ci.org/). By default you will get linting, spec tests and integration tests with [kitchen-dokken]. -Integration tests of this repository are conducted using [DigitalOcean](http://digitalocean.com/). +Integration tests with [kitchen-dokken] do not cover everything as they run in the container environment. +Full integration tests can be executed using [DigitalOcean](http://digitalocean.com/). -If you want to have integration tests for your fork, you will have to add following [environment variables](https://docs.travis-ci.com/user/environment-variables/#Defining-Variables-in-Repository-Settings) in the settings of your fork: +If you want to have full integration tests for your fork, you will have to add following [environment variables](https://docs.travis-ci.com/user/environment-variables/#Defining-Variables-in-Repository-Settings) in the settings of your fork: - `DIGITALOCEAN_ACCESS_TOKEN` - [access token for DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2) - `CI_SSH_KEY` - private part of some ssh key, available on DigitalOcean for your instances, in base64 encoded form (e.g. `cat id_rsa | base64 -w0 ; echo`) - `DIGITALOCEAN_SSH_KEY_IDS` - ID in DigitalOcean of `CI_SSH_KEY`, see [this](https://github.com/test-kitchen/kitchen-digitalocean#installation-and-setup) for more information @@ -165,6 +183,7 @@ If you want to have integration tests for your fork, you will have to add follow * Christoph Hartmann [chris-rock](https://github.com/chris-rock) * Edmund Haselwanter [ehaselwanter](https://github.com/ehaselwanter) * Patrick Meier [atomic111](https://github.com/atomic111) +* Artem Sidorenko [artem-sidorenko](https://github.com/artem-sidorenko) This cookbook is mostly based on guides by: @@ -202,3 +221,4 @@ limitations under the License. [3]: https://coveralls.io/r/dev-sec/chef-os-hardening [4]: https://gemnasium.com/dev-sec/chef-os-hardening [5]: https://gitter.im/dev-sec/general +[kitchen-dokken]: https://github.com/someara/kitchen-dokken diff --git a/Rakefile b/Rakefile index 3a0592a6..887ae111 100644 --- a/Rakefile +++ b/Rakefile @@ -65,24 +65,30 @@ end desc 'Run kitchen integration tests' task :kitchen do + SSH_KEY_FILE = '~/.ssh/ci_id_rsa'.freeze + SSH_KEY_ENV_VAR_NAME = 'CI_SSH_KEY'.freeze concurrency = ENV['CONCURRENCY'] || 1 instance = ENV['INSTANCE'] || '' args = ENV['CI'] ? '--destroy=always' : '' - sh('sh', '-c', "bundle exec kitchen test -c #{concurrency} #{args} #{instance}") -end -desc 'Prepare CI environment for DigitalOcean usage' -task :prepare_do_env do - SSH_KEY_FILE = '~/.ssh/ci_id_rsa'.freeze - ENV_VAR_NAME = 'CI_SSH_KEY'.freeze + if ENV['CI'] && ENV['KITCHEN_LOCAL_YAML'] == '.kitchen.do.yml' + puts 'Preparing CI environment for DigitalOcean...' + + ['DIGITALOCEAN_ACCESS_TOKEN', 'DIGITALOCEAN_SSH_KEY_IDS', SSH_KEY_ENV_VAR_NAME].each do |var| + unless ENV[var] # rubocop:disable Style/Next + puts "#{var} isn't defined. Skipping the task" + # We are not raising exit 1 as we want our CI tests in the forks to succeed. + # Our forks usually do not have the DO environment variables and are tested via dokken + exit + end + end - ['DIGITALOCEAN_ACCESS_TOKEN', 'DIGITALOCEAN_SSH_KEY_IDS', ENV_VAR_NAME].each do |var| - raise "Environment variable #{var} should be set" unless ENV[var] + ssh_file = File.expand_path(SSH_KEY_FILE) + dir = File.dirname(ssh_file) + Dir.mkdir(dir, 0o700) unless Dir.exist?(dir) + File.open(ssh_file, 'w') { |f| f.puts Base64.decode64(ENV[SSH_KEY_ENV_VAR_NAME]) } + File.chmod(0o600, ssh_file) end - ssh_file = File.expand_path(SSH_KEY_FILE) - dir = File.dirname(ssh_file) - Dir.mkdir(dir, 0o700) unless Dir.exist?(dir) - File.open(ssh_file, 'w') { |f| f.puts Base64.decode64(ENV[ENV_VAR_NAME]) } - File.chmod(0o600, ssh_file) + sh('sh', '-c', "bundle exec kitchen test -c #{concurrency} #{args} #{instance}") end diff --git a/recipes/default.rb b/recipes/default.rb index c0bed613..0b03c312 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -20,14 +20,31 @@ # limitations under the License. # -include_recipe('os-hardening::packages') -include_recipe('os-hardening::limits') -include_recipe('os-hardening::login_defs') -include_recipe('os-hardening::minimize_access') -include_recipe('os-hardening::pam') -include_recipe('os-hardening::profile') -include_recipe('os-hardening::securetty') -include_recipe('os-hardening::suid_sgid') if node['os-hardening']['security']['suid_sgid']['enforce'] -include_recipe('os-hardening::sysctl') -include_recipe('os-hardening::auditd') -include_recipe('os-hardening::selinux') if node['platform_family'] == 'rhel' || node['platform_family'] == 'fedora' +# here we try to determine which components should be included. +# You can control the behaviour via setting the node['os-hardening']['components'][recipe_name] +# to true (to include it) or to false (to skip it) on the override level, e.g. +# +# override['os-hardening']['components']['sysctl'] = false +# + +# generic components, include them per default +%w[packages limits login_defs minimize_access pam profile securetty].each do |cp| + node.default['os-hardening']['components'][cp] = true +end + +node.default['os-hardening']['components']['suid_sgid'] = node['os-hardening']['security']['suid_sgid']['enforce'] + +# components which are not suitable for containers +unless node['virtualization']['system'] =~ /^(lxc|docker)$/ && node['virtualization']['role'] == 'guest' + node.default['os-hardening']['components']['sysctl'] = true + node.default['os-hardening']['components']['auditd'] = true + + # selinux should be included only on RH based systems + node.default['os-hardening']['components']['selinux'] = + node['platform_family'] == 'rhel' || node['platform_family'] == 'fedora' +end + +# include all required components +node['os-hardening']['components'].each do |component, state| + include_recipe "#{cookbook_name}::#{component}" if state +end diff --git a/recipes/minimize_access.rb b/recipes/minimize_access.rb index e67b7e2d..0dbc4b76 100644 --- a/recipes/minimize_access.rb +++ b/recipes/minimize_access.rb @@ -57,5 +57,10 @@ # /var/log should restricted to root or syslog on ubuntu systems directory '/var/log' do owner 'root' - group node['platform'] == 'ubuntu' ? 'syslog' : 'root' + # ubuntu with containers does not have rsyslog installed and syslog group does not exist + if node['platform'] == 'ubuntu' && node['packages']['rsyslog'] + group 'syslog' + else + group 'root' + end end