cloudamatic/mu

View on GitHub
cookbooks/mu-tools/recipes/apply_security.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Cookbook Name:: mu-tools
# Recipe:: apply_security
#
# Copyright:: Copyright (c) 2014 eGlobalTech, Inc., all rights reserved
#
# Licensed under the BSD-3 license (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the root of the project or at
#
#         http://egt-labs.com/mu/LICENSE.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Apply security patterns for hardening

if !node['application_attributes']['skip_recipes'].include?('apply_security')
  case node['platform_family']
    when "rhel", "amazon"
      include_recipe "mu-tools::aws_api"
      include_recipe "mu-tools::google_api"
  
      if node['platform_version'].to_i < 6
        package "policycoreutils"
      elsif node['platform_version'].to_i < 8
        package "policycoreutils-python"
      else
        package "xfsprogs"
        package "xfsprogs-devel"
        package "policycoreutils-python-utils"
      end
  
      %w{ authconfig aide }.each do |pkg|
        package "apply_security package #{pkg}" do
          package_name pkg
        end
      end

      if node['platform_version'].to_i < 8
        package "ntp"
        bash "NTP" do
          user "root"
          code <<-EOH
                    chkconfig ntpd on
                    ntpdate pool.ntp.org
                    service ntpd start
          EOH
        end
      else
        package "chrony"
        service "chronyd"
      end

      execute "enable manual auditd restarts" do
        command "sed -i s/RefuseManualStop=yes/#RefuseManualStop=yes/ /usr/lib/systemd/system/auditd.service ; pkill auditd"
        ignore_failure true
        action :nothing
        only_if "grep ^RefuseManualStop=yes /usr/lib/systemd/system/auditd.service"
      end
  
      service "auditd" do
        action :nothing
        notifies :run, "execute[enable manual auditd restarts]", :before
      end
  
      if node['platform_version'].to_i < 7
        cookbook_file "/etc/audit/audit.rules" do
          source "etc/audit/stig.rules"
          notifies :restart, "service[auditd]", :delayed
        end
      end
  
      file "/etc/profile.d/tmout.sh" do
        content "TMOUT=900
  readonly TMOUT
  export TMOUT
  "
      end
  
      file "/etc/profile.d/autologout.csh" do
        content "set -r autologout 15\n"
      end
  
  
      #File integrity checking. Default configuration
      bash "AIDE" do
        code <<-EOH
                  aide --init
                  mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
        EOH
        not_if { File.exist?("/var/lib/aide/aide.db.gz") }
      end
      cron "AIDE daily scan" do
        action :create
        minute "0"
        hour "5"
        user "root"
        command "/usr/sbin/aide --check"
        only_if { File.exist?("/usr/sbin/aide") }
      end
  
      cookbook_file "/etc/security/limits.conf" do
        source "etc/security/limits.conf"
        mode 0644
        owner "root"
        group "root"
      end
      cookbook_file "/etc/sysctl.conf" do
        source "etc/sysctl.conf"
        mode 0644
        owner "root"
        group "root"
      end
  
      cookbook_file "/etc/sysconfig/init" do
        source "etc/sysconfig/init"
        mode 0644
        owner "root"
        group "root"
      end
  
  
      bash "Logging and Auditing" do
        code <<-EOH
                  #4.1.4 Create and Set Permissions on rsyslog Log Files
                  #find `awk '/^ *[^#$]/ { print $2 }' /etc/rsyslog.conf | egrep -o "/.*"` -perm /o+rwx
                  chmod og-rwx /var/log/boot.log
        EOH
      end
  
      bash "Network Configuration and Firewalls" do
        code <<-EOH
                  #5.1.2 Disable Send Packet Redirects
                  sysctl -w net.ipv4.conf.default.send_redirects=0
                  sysctl -w net.ipv4.conf.all.send_redirects=0
                  sysctl -w net.ipv4.route.flush=1
  
                  #5.2.2 Disable ICMP Redirect Acceptance
                  sysctl -w net.ipv4.conf.all.accept_redirects=0
                  sysctl -w net.ipv4.conf.default.accept_redirects=0
                  sysctl -w net.ipv4.route.flush=1
  
                  #5.2.4 Log Suspicious Packets
                  sysctl -w net.ipv4.conf.all.log_martians=1
                  sysctl -w net.ipv4.conf.default.log_martians=1
                  sysctl -w net.ipv4.route.flush=1
  
                  #5.4.1.1 Disable IPv6 Router Advertisements
                  sysctl -w net.ipv6.conf.all.accept_ra=0
                  sysctl -w net.ipv6.conf.default.accept_ra=0
                  sysctl -w net.ipv6.route.flush=1
  
                  #5.4.1.2 Disable IPv6 Redirect Acceptance
                  sysctl -w net.ipv6.conf.all.accept_redirects=0
                  sysctl -w net.ipv6.conf.default.accept_redirects=0
                  sysctl -w net.ipv6.route.flush=1
        EOH
      end
  
  
      if node['root_login_disabled']
        #some code
      end
  
  
      bash "System Access, Authentication and Authorization" do
        user "root"
        code <<-EOH
                  #6.1 Configure cron and anacron
                  
                  #6.1.11 Restrict at/cron to Authorized Users
                  rm -f /etc/cron.deny
  
                  #6.1.3 Set User/Group Owner and Permission on /etc/anacrontab
                  chmod og-rwx /etc/anacrontab
  
                  #6.1.4 Set User/Group Owner and Permission on /etc/crontab
                  chmod og-rwx /etc/crontab
  
                  #6.1.5 Set User/Group Owner and Permission on /etc/cron.hourly
                  chmod og-rwx /etc/cron.hourly
  
                  #6.1.6 Set User/Group Owner and Permission on /etc/cron.daily
                  chmod og-rwx /etc/cron.daily
  
                  #6.1.7 Set User/Group Owner and Permission on /etc/cron.weekly
                  chmod og-rwx /etc/cron.weekly
  
                  #6.1.8 Set User/Group Owner and Permission on /etc/cron.monthly
                  chmod og-rwx /etc/cron.monthly
  
                  #6.1.9 Set User/Group Owner and Permission on /etc/cron.d
                  chmod og-rwx /etc/cron.d
  
                  #6.1.10 Restrict at Daemon
                  touch /etc/at.allow
                  chown root:root /etc/at.allow
                  chmod og-rwx /etc/at.allow
  
                  #6.1.11 Restrict at/cron to Authorized Users
                  touch /etc/cron.allow
                  chown root:root /etc/cron.allow
                  chmod og-rwx /etc/cron.allow
  
        EOH
      end
  
      # 6.2 Configure SSH
      begin
        resources('service[sshd]')
      rescue Chef::Exceptions::ResourceNotFound
        service "sshd" do
          action [:enable, :start]
        end
      end
  
      # Make sure we don't lock ourselves out of nodes when setting AllowGroups
      # in sshd.
      if !node['application_attributes']['sshd_allow_groups'].empty?
        group "mu_sshd_system_login"
        ['root', 'centos', 'ec2-user'].each { |sys_login|
          group "add #{sys_login} to mu_sshd_system_login" do
            group_name "mu_sshd_system_login"
            members sys_login
            append true
            ignore_failure true
          end
        }
        node.override['application_attributes']['sshd_allow_groups'] = "mu_sshd_system_login "+node['application_attributes']['sshd_allow_groups']
      end rescue NoMethodError
  
      template "/etc/ssh/sshd_config" do
        source "sshd_config.erb"
        owner "root"
        group "root"
        mode 0600
        cookbook "mu-tools"
        notifies :restart, "service[sshd]", :immediately
      end
  
      cookbook_file "/etc/issue.net" do
        source node['banner']['path']
        mode 0644
        owner "root"
        group "root"
      end
  
      cookbook_file "/etc/issue" do
        source node['banner']['path']
        mode 0644
        owner "root"
        group "root"
      end
      #        cookbook_file "/etc/motd" do
      #            source node['banner']['path']
      #            mode 0644
      #            owner "root"
      #            group "root"
      #        end
      #        cookbook_file "/etc/pam.d/su" do
      #            source "etc/pam.d/su"
      #            mode 0644
      #            owner "root"
      #            group "root"
      #        end
      # 6.3 Configure PAM
      # 6.3.2 Set Password Creation Requirement Parameters Using pam_cracklib
#      template "/etc/pam.d/password-auth-local" do
#        source "etc_pamd_password-auth.erb"
#        mode 0644
#      end
#      link "/etc/pam.d/password-auth" do
#        to "/etc/pam.d/password-auth-local"
#      end
      #6.3.3 Set Lockout for Failed Password Attempts
#      template "/etc/pam.d/system-auth-local" do
#        source "etc_pamd_system-auth.erb"
#        mode 0644
#      end
#      link "/etc/pam.d/system-auth" do
#        to "/etc/pam.d/system-auth-local"
#      end
  
      #SV-50303r1_rule/SV-50304r1_rule
      execute "chown root:root /etc/shadow"
      #SV-50305r1_rule
      execute "chmod 0000 /etc/shadow"
      #SV-50243r1_rule/SV-50248r1_rule
      execute "chown root:root /etc/gshadow"
      #SV-50249r1_rule
      execute "chmod 0000 /etc/gshadow"
      #SV-50250r1_rule/SV-50251r1_rule
      execute "chown root:root /etc/passwd"
      #SV-50257r1_rule
      execute "chmod 0644 /etc/passwd"
      #SV-50258r1_rule/SV-50259r1_rule
      execute "chown root:root /etc/group"
      #SV-50261r1_rule
      execute "chmod 0644 /etc/group"
  
      %w{ /lib /lib64 /usr/lib /usr/lib64 }.each do |dir|
        execute "chown -R root #{dir}"
      end
  
  
      # 7.1 Set Shadow Password Suite Parameters (/etc/login.defs)
      cookbook_file "/etc/login.defs" do
        source "etc/login.defs"
        mode 0644
        owner "root"
        group "root"
      end
  
      # 7.4 Set default umask for users
      cookbook_file "/etc/bashrc" do
        source "etc/bashrc"
        mode 0644
        owner "root"
        group "root"
      end
  
      cookbook_file "/etc/profile" do
        source "etc/profile"
        mode 0644
        owner "root"
        group "root"
      end
  
      # 7.5 Lock Inactive User Accounts
      bash "Lock Inactive Accounts" do
        user "root"
        code <<-EOH
                  useradd -D -f 35
        EOH
      end
  
      # disable some filesystems
      ["cramfs", "freevxfs", "jffs2", "hfs", "hfsplus", "squashfs", "udf"].each { |fs|
        execute "disable #{fs}" do
          command "echo 'install #{fs} /bin/true' >> /etc/modprobe.d/dist.conf"
          not_if "grep '^install #{fs} ' /etc/modprobe.d/dist.conf"
        end
      }

      mu_tools_disk "swap" do
        device node['application_attributes']['swap']['mount_device']
        size node['application_attributes']['swap']['volume_size_gb']
        swap true
      end

      mu_tools_disk "/home" do
        device node['application_attributes']['home']['mount_device']
        size node['application_attributes']['home']['volume_size_gb']
        preserve_data true
      end

      Chef::Log.info("Value of login_disabled is #{node['root_login_disabled']}")
  
      ruby_block "do a bunch of weird stuff" do # ~FC014
        block do
          cmd = Mixlib::ShellOut.new('chcon -Rv --type=user_home_t /home')
          cmd.run_command
          cmd = Mixlib::ShellOut.new('rm -rf /tmp/moveusers.tgz')
          cmd.run_command
          # `chcon -Rv --type=user_home_t /home`
          # `rm -rf /tmp/moveusers.tgz`
          valid_users="AllowUsers root"
          node['etc']['passwd'].each do |user, data|
            if data['uid'] >= 500 && data['shell'] !~ /nologin/ then
              valid_users += " " + user
            end
          end
          Chef::Log.info("Enabling ssh users #{valid_users}")
          fe = Chef::Util::FileEdit.new("/etc/ssh/sshd_config")
          fe.search_file_replace_line(/^AllowUsers.*$/, valid_users)
          fe.write_file
        end
        only_if { ::File.exist?("/tmp/moveusers.tgz") }
      end
  
      execute "mount -oremount /dev/shm" do
        action :nothing
      end
      mount "/dev/shm" do
        device "tmpfs"
        options "nodev,nosuid,noexec"
        action [:enable, :mount]
        notifies :run, "execute[mount -oremount /dev/shm]", :immediately
      end
  
      # XXX This is where ephemeral storage seems to land, usually. Usually. We'd
      # probably like a more robust way of identifying it.
      if !node['tmp_dev'].nil?
        if node['platform_version'].to_i == 6
          execute "mkfs.ext4 #{node['tmp_dev']}" do
            not_if "tune2fs -l #{node['tmp_dev']}"
          end
        elsif node['platform_version'].to_i == 7
          execute "mkfs.xfs -i size=512 #{node['tmp_dev']}" do
            not_if "xfs_info #{node['tmp_dev']}"
          end
        end
  
        mount "/tmp" do
          device node['tmp_dev']
          options "nodev,nosuid,noexec"
          action [:mount, :enable]
          notifies :run, "execute[fix /tmp permissions]", :immediately
        end
        mount "/var/tmp" do
          device "/tmp"
          options "bind"
          action [:mount, :enable]
        end
        execute "fix /tmp permissions" do
          command "chmod 1777 /tmp ; /sbin/restorecon -R /tmp"
        end
      end rescue NoMethodError
  
    when "ubuntu"
      # Make sure we don't lock ourselves out of nodes when setting AllowGroups
      # in sshd.
      if !node['application_attributes']['sshd_allow_groups'].empty?
        group "mu_sshd_system_login"
        ['root', 'ubuntu'].each { |sys_login|
          group "mu_sshd_system_login" do
            members sys_login
            append true
            ignore_failure true
          end
        }
        node.override['application_attributes']['sshd_allow_groups'] = "mu_sshd_system_login "+node['application_attributes']['sshd_allow_groups']
      end rescue NoMethodError
  
      template "/etc/ssh/sshd_config" do
        source "sshd_config.erb"
        owner "root"
        group "root"
        mode 0600
        cookbook "mu-tools"
        notifies :restart, "service[sshd]", :immediately
      end
      cookbook_file "/etc/issue.net" do
        source node['banner']['path']
        mode 0644
        owner "root"
        group "root"
      end
      cookbook_file "/etc/motd.tail" do
        source node['banner']['path']
        mode 0644
        owner "root"
        group "root"
      end
    else
      Chef::Log.info("Unsupported platform #{node['platform']}")
  end
end