├── .gitignore ├── scripts ├── zerodisk.sh ├── cleanup.sh ├── oscap-pci-dss.sh └── centos7-hardened-install.sh ├── README.md ├── LICENSE ├── packer └── centos7-hardened.json ├── .travis.yml └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | # Cache objects 2 | packer_cache/ 3 | 4 | # For built boxes 5 | *.box 6 | 7 | # ignore manifest 8 | packer-manifest.json 9 | -------------------------------------------------------------------------------- /scripts/zerodisk.sh: -------------------------------------------------------------------------------- 1 | # Zero out all the free space to save space in the final image: 2 | dd if=/dev/zero of=/EMPTY bs=1M 3 | rm -f /EMPTY 4 | dd if=/dev/zero of=/home/EMPTY bs=1M 5 | rm -f /home/EMPTY 6 | dd if=/dev/zero of=/tmp/EMPTY bs=1M 7 | rm -f /tmp/EMPTY 8 | dd if=/dev/zero of=/var/EMPTY bs=1M 9 | rm -f /var/EMPTY 10 | dd if=/dev/zero of=/var/log/EMPTY bs=1M 11 | rm -f /var/log/EMPTY 12 | dd if=/dev/zero of=/var/log/audit/EMPTY bs=1M 13 | rm -f /var/log/audit/EMPTY 14 | dd if=/dev/zero of=/opt/EMPTY bs=1M 15 | rm -f /opt/EMPTY 16 | dd if=/dev/zero of=/usr/EMPTY bs=1M 17 | rm -f /usr/EMPTY 18 | 19 | # Output mounts / disk space 20 | cat /etc/fstab 21 | df -h 22 | -------------------------------------------------------------------------------- /scripts/cleanup.sh: -------------------------------------------------------------------------------- 1 | # Stop logging 2 | service rsyslog stop 3 | service auditd stop 4 | 5 | # Cleanup packages / yum 6 | yum -y clean all 7 | 8 | # Shrink / rm logs 9 | logrotate -f /etc/logrotate.conf 10 | rm -f /var/log/*-???????? /var/log/*.gz 11 | rm -f /var/log/dmesg.old 12 | rm -rf /var/log/anaconda 13 | cat /dev/null > /var/log/audit/audit.log 14 | cat /dev/null > /var/log/wtmp 15 | cat /dev/null > /var/log/lastlog 16 | cat /dev/null > /var/log/grubby 17 | 18 | # cleanup networking 19 | rm -f /etc/udev/rules.d/70* 20 | sed -i '/UUID/d' /etc/sysconfig/network-scripts/ifcfg-e* 21 | sed -i '/HWADDR/d' /etc/sysconfig/network-scripts/ifcfg-e* 22 | 23 | # Cleanup user SSH 24 | rm -f /etc/ssh/*key* 25 | rm -rf ~/.ssh/ 26 | 27 | # Clean up user history 28 | rm -f ~/.bash_history 29 | unset HISTFILE 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # centos7-hardened 2 | Configuration for an Oscap PCI-DSS hardened CentOS 7 AMI built using Packer. 3 | 4 | # Why 5 | ## Overview 6 | As a consultant I work with clients on a range of projects across a range of 7 | business sectors. Currently I'm working with a major InsureTech firm that 8 | produces and runs the software for some of the UK's biggest insurers. 9 | 10 | They are a PCI-DSS level 1 merchant and they handle a lot of personally identifiable 11 | data. 12 | 13 | ## Current AMI's 14 | Currently the CentOS AMI's available in the AWS Market Place are great and certainly 15 | secure enough for general purpose use however they don't have any best practice 16 | or advised security configuration applied. 17 | 18 | There is a couple of hardened AMI's available at an extra cost: 19 | CIS CentOS 7: https://aws.amazon.com/marketplace/pp/B01K5TVAOA 20 | OpenLogic Hardened: https://aws.amazon.com/marketplace/pp/B01G7PWQXK 21 | 22 | ## Community 23 | I wanted to get to grips with building custom OS AMI's in AWS and make it all 24 | open to the wider tech community for free. It was a great learning exercise and 25 | a great opportunity to give a secure OS to the public Marketplace that others can 26 | make use of. 27 | 28 | # How 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /packer/centos7-hardened.json: -------------------------------------------------------------------------------- 1 | { 2 | "min_packer_version": "0.8.6", 3 | "variables": { 4 | "aws_access_key": "", 5 | "aws_secret_key": "", 6 | "aws_session_token": "", 7 | "aws_instance_type": "t2.small", 8 | "name": "centos7-hardened", 9 | "description": "CentOS 7 Hardened Installation" 10 | }, 11 | "provisioners": [{ 12 | "type": "shell", 13 | "scripts": [ 14 | "scripts/centos7-hardened-install.sh", 15 | "scripts/oscap-pci-dss.sh", 16 | "scripts/cleanup.sh", 17 | "scripts/zerodisk.sh" 18 | ], 19 | "start_retry_timeout": "15m", 20 | "execute_command": "echo 'centos'|sudo -S sh '{{.Path}}'" 21 | }], 22 | "builders": [{ 23 | "name": "centos7-hardened", 24 | "type": "amazon-ebs", 25 | "access_key": "{{user `aws_access_key_id`}}", 26 | "secret_key": "{{user `aws_secret_key`}}", 27 | "token": "{{user `aws_session_token`}}", 28 | "region": "us-east-1", 29 | "source_ami": "ami-ae7bfdb8", 30 | "instance_type": "{{user `aws_instance_type`}}", 31 | "ami_block_device_mappings": [{ 32 | "device_name": "/dev/sda1", 33 | "volume_size": 8, 34 | "volume_type": "gp2", 35 | "delete_on_termination": true 36 | }], 37 | "launch_block_device_mappings": [{ 38 | "device_name": "/dev/sda1", 39 | "volume_size": 8, 40 | "volume_type": "gp2", 41 | "delete_on_termination": true 42 | }], 43 | "force_deregister": true, 44 | "force_delete_snapshot": true, 45 | "ssh_username": "centos", 46 | "ami_name": "{{user `name`}} {{timestamp}}", 47 | "ami_description": "{{user `description`}}", 48 | "ami_groups": ["all"], 49 | "ssh_pty": true, 50 | "ssh_timeout": "10m" 51 | }], 52 | "post-processors": [{ 53 | "type": "manifest" 54 | }] 55 | } 56 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | os: 5 | - linux 6 | 7 | env: 8 | global: 9 | - secure: PdFuON9YI5MKZa1li/xIyBdhuHJvxpXnM4/OeffrZclYBbS4PX+Y9ueAYeKAVW/z3lB49Io23I5RU35KglWyHambxXvPwnELcJO5Ew1gMdW/45Rv6ZW9tYiiiSy9XPBJKZXrLWufyzEwvRPwQxoMHjmliIxZB6tqsy5t2eJOxJP7ykw2FUMSqDWZ0tYToIDq4c7YvWDy1xX8MHblhUIMde0cz/nFIvPy81et76rH53KQjlGW6PIcTI+hcy6nZIwPlUDavnWiRAk+aiZOJikQCYeGxyGd6ZY2kkt7iCHCq1A4cBOGS0hMoQyUK0ZucSr1uvJRWaKqrZZPj+Ib7zyiJuhEabzBNesYZ7MvNa9BChqllxj0kZRjmUGu6TR/M0xYfrto8TWnI7LfmuW1EbEYb4iTWr6EtB4TX/bs6TKi8Z/QEu292Vnh4bYwYoYMiH5jr2OafoaWl4mVylnLJyqlLoq5TzazYcfEFNJ5Apoa48s9UDsPEPTY/hE3AptDqPRPN1UfkcPqCozroXcMg8sp7yMw0g0VoL6PAjFzpFsrTixhE6fspfXGZ73ERK5Tu1XoELG9jWiT/z9z8O5LtTOLe0G3sGDSZ6juXav/AHnRBy4gP0GK+7FHsG+yMoixCOGjoUmEpCTqwrU4ifTAFzZKXJyJ+EnT2pw0VKTfroViD4A= 10 | - secure: nU1JvKJHikjZ3frkQ1jibLs2bqeFxhmbIGIIb4hmWMnQ7M+gwEtxNMc6OtroFJsMMXxY294hLpheoOABTKWMSEuufQwZqdGTYVaLHKJXKgz/vLf+f5hUWi5l89XkjXw6dOpeGVjZWXMD5r+DFyqdgIXFNAvJBPJUivaMCMyni6R08Rn97iW0r61MXb7HUFNJDeJwbksDsOTmosTe4G+lCrFgEvODzxvAv+IOruBfwQiI5ZYhtFUQNQ99kBCWvqenwi8FUc2bdPq+kuVoigqZXlGG886yqhNl1XT3snxDJVrAU9BBf4PnKyReZqOsfBORiu65iiXrQ5VDZnXTlY7+B5vfqsdX3SB+d4ezhovOH8r1SWLGKvnxceNzbAcP+nCbVeUY6JCNaeaA8aaWCcvNbjkkplqjjyxuNXtGdTaguDP5DzqqZlV+qryEMRZTwbHK0mZve/2ksdlJ8pvoyFcLguNb9gIO4oIvyVdA+EUb0YTcyGqUUXqDf3vC1zfrMmMdeEw/G8QkS3jh9AZv8xaa0KhGayww7ntQGzBzX/VjSj49iLhC89VdTW73ycIK6hJhNoZ6/ue0uFijbl7V+oJsha5qUCS0IyxTInC5meb5up6UHquVnRD4ZR0029xj0GjQ8B+D/F/A5meUOdma/vIcILQzlF0J8CAlZxrfrduBU0M= 11 | 12 | install: 13 | - curl -o /tmp/packer.zip -L "https://releases.hashicorp.com/packer/1.0.0/packer_1.0.0_linux_amd64.zip" 14 | - sudo unzip -o -d /usr/local/bin /tmp/packer.zip 15 | 16 | script: 17 | - make build 18 | - cat packer-manifest.json 19 | 20 | notifications: 21 | email: 22 | recipients: 23 | - tim.j.birkett@gmail.com 24 | on_failure: change 25 | on_success: change 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: help 2 | help: 3 | @echo "Available commands:" 4 | @echo " test-env: Ensure requirements are met for builds to run" 5 | @echo " validate: Validates all packer json configuration files" 6 | @echo " test: Tests environments and validates configuations" 7 | @echo " ap-northeast-1: Build the hardened CentOS 7 AMI in region: ap-northeast-1" 8 | @echo " ap-northeast-2: Build the hardened CentOS 7 AMI in region: ap-northeast-2" 9 | @echo " ap-south-1: Build the hardened CentOS 7 AMI in region: ap-south-1" 10 | @echo " ap-southeast-1: Build the hardened CentOS 7 AMI in region: ap-southeast-1" 11 | @echo " ap-southeast-2: Build the hardened CentOS 7 AMI in region: ap-southeast-2" 12 | @echo " ca-central-1: Build the hardened CentOS 7 AMI in region: ca-central-1" 13 | @echo " eu-central-1: Build the hardened CentOS 7 AMI in region: eu-central-1" 14 | @echo " eu-west-1: Build the hardened CentOS 7 AMI in region: eu-west-1" 15 | @echo " eu-west-2: Build the hardened CentOS 7 AMI in region: eu-west-2" 16 | @echo " sa-east-1: Build the hardened CentOS 7 AMI in region: sa-east-1" 17 | @echo " us-east-1: Build the hardened CentOS 7 AMI in region: us-east-1" 18 | @echo " us-east-2: Build the hardened CentOS 7 AMI in region: us-east-2" 19 | @echo " us-west-1: Build the hardened CentOS 7 AMI in region: us-west-1" 20 | @echo " us-west-2: Build the hardened CentOS 7 AMI in region: us-west-2" 21 | @echo " all: Build the CentOS 7 hardened AMI for all AWS regions" 22 | @echo " help: This help message" 23 | 24 | .PHONY: test-env 25 | test-env: 26 | @# Searches for required settings as detailed here: 27 | @# https://www.packer.io/docs/builders/amazon.html#specifying-amazon-credentials 28 | @packer version 29 | @echo "Searching for AWS Credentials... " ; \ 30 | if [ -r "${AWS_SHARED_CREDENTIALS_FILE }" ] ; \ 31 | then \ 32 | echo "ok [custom credentials file]" ; \ 33 | elif [ -r ~/.aws/credentials ] ; \ 34 | then \ 35 | echo "ok [user credentials file]" ; \ 36 | elif [ -z "${AWS_ACCESS_KEY_ID}" ] && [ -z "${AWS_ACCESS_KEY}" ] && \ 37 | [ -z "${AWS_SECRET_ACCESS_KEY}" ] && [ -z "${AWS_SECRET_KEY}" ] ; \ 38 | then \ 39 | echo "error [no credentials found]" ; \ 40 | exit 1 ; \ 41 | else \ 42 | echo "ok [environment variables]" ; \ 43 | fi ; \ 44 | echo "Using AWS Profile: " ; [ -z "${AWS_PROFILE}" ] && echo "default" || echo "${AWS_PROFILE}" 45 | 46 | .PHONY: validate 47 | validate: 48 | @for build in packer/*.json; do \ 49 | echo "Validating $${build}... " ;\ 50 | packer validate $${build} ; \ 51 | done 52 | 53 | .PHONY: test 54 | test: test-env validate 55 | 56 | .PHONY: build 57 | build: test 58 | @echo "Building CentOS 7 hardened AMI..." 59 | packer build -force packer/centos7-hardened.json 60 | -------------------------------------------------------------------------------- /scripts/oscap-pci-dss.sh: -------------------------------------------------------------------------------- 1 | # Output / Remediate PCI-DSS 2 | 3 | # Create secure audit rules 4 | cat < /etc/audit/rules.d/audit.rules 5 | # DISA STIG Audit Rules 6 | ## Add keys to the audit rules below using the -k option to allow for more 7 | ## organized and quicker searches with the ausearch tool. See auditctl(8) 8 | ## and ausearch(8) for more information. 9 | # Remove any existing rules 10 | -D 11 | # Increase kernel buffer size 12 | -b 16384 13 | # Failure of auditd causes a kernel panic 14 | -f 2 15 | ########################### 16 | ## DISA STIG Audit Rules ## 17 | ########################### 18 | # Watch syslog configuration 19 | -w /etc/rsyslog.conf 20 | -w /etc/rsyslog.d/ 21 | # Watch PAM and authentication configuration 22 | -w /etc/pam.d/ 23 | -w /etc/nsswitch.conf 24 | # Watch system log files 25 | -w /var/log/messages 26 | -w /var/log/audit/audit.log 27 | -w /var/log/audit/audit[1-4].log 28 | # Watch audit configuration files 29 | -w /etc/audit/auditd.conf -p wa 30 | -w /etc/audit/audit.rules -p wa 31 | # Watch login configuration 32 | -w /etc/login.defs 33 | -w /etc/securetty 34 | -w /etc/resolv.conf 35 | # Watch cron and at 36 | -w /etc/at.allow 37 | -w /etc/at.deny 38 | -w /var/spool/at/ 39 | -w /etc/crontab 40 | -w /etc/anacrontab 41 | -w /etc/cron.allow 42 | -w /etc/cron.deny 43 | -w /etc/cron.d/ 44 | -w /etc/cron.hourly/ 45 | -w /etc/cron.weekly/ 46 | -w /etc/cron.monthly/ 47 | # Watch shell configuration 48 | -w /etc/profile.d/ 49 | -w /etc/profile 50 | -w /etc/shells 51 | -w /etc/bashrc 52 | -w /etc/csh.cshrc 53 | -w /etc/csh.login 54 | # Watch kernel configuration 55 | -w /etc/sysctl.conf 56 | -w /etc/modprobe.conf 57 | # Watch linked libraries 58 | -w /etc/ld.so.conf -p wa 59 | -w /etc/ld.so.conf.d/ -p wa 60 | # Watch init configuration 61 | -w /etc/rc.d/init.d/ 62 | -w /etc/sysconfig/ 63 | -w /etc/inittab -p wa 64 | -w /etc/rc.local 65 | -w /usr/lib/systemd/ 66 | -w /etc/systemd/ 67 | # Watch filesystem and NFS exports 68 | -w /etc/fstab 69 | -w /etc/exports 70 | # Watch xinetd configuration 71 | -w /etc/xinetd.conf 72 | -w /etc/xinetd.d/ 73 | # Watch Grub2 configuration 74 | -w /etc/grub2.cfg 75 | -w /etc/grub.d/ 76 | # Watch TCP_WRAPPERS configuration 77 | -w /etc/hosts.allow 78 | -w /etc/hosts.deny 79 | # Watch sshd configuration 80 | -w /etc/ssh/sshd_config 81 | # Audit system events 82 | -a always,exit -F arch=b32 -S acct -S reboot -S sched_setparam -S sched_setscheduler -S setrlimit -S swapon 83 | -a always,exit -F arch=b64 -S acct -S reboot -S sched_setparam -S sched_setscheduler -S setrlimit -S swapon 84 | # Audit any link creation 85 | -a always,exit -F arch=b32 -S link -S symlink 86 | -a always,exit -F arch=b64 -S link -S symlink 87 | ############################## 88 | ## NIST 800-53 Requirements ## 89 | ############################## 90 | #2.6.2.4.1 Records Events that Modify Date and Time Information 91 | -a always,exit -F arch=b32 -S adjtimex -S stime -S settimeofday -S clock_settime -k time-change 92 | -a always,exit -F arch=b64 -S adjtimex -S settimeofday -S clock_settime -k time-change 93 | -w /etc/localtime -p wa -k time-change 94 | #2.6.2.4.2 Record Events that Modify User/Group Information 95 | -w /etc/group -p wa -k identity 96 | -w /etc/passwd -p wa -k identity 97 | -w /etc/gshadow -p wa -k identity 98 | -w /etc/shadow -p wa -k identity 99 | -w /etc/security/opasswd -p wa -k identity 100 | #2.6.2.4.3 Record Events that Modify the Systems Network Environment 101 | -a always,exit -F arch=b32 -S sethostname -S setdomainname -k audit_network_modifications 102 | -a always,exit -F arch=b64 -S sethostname -S setdomainname -k audit_network_modifications 103 | -w /etc/issue -p wa -k audit_network_modifications 104 | -w /etc/issue.net -p wa -k audit_network_modifications 105 | -w /etc/hosts -p wa -k audit_network_modifications 106 | -w /etc/sysconfig/network -p wa -k audit_network_modifications 107 | #2.6.2.4.4 Record Events that Modify the System Mandatory Access Controls 108 | -w /etc/selinux/ -p wa -k MAC-policy 109 | #2.6.2.4.5 Ensure auditd Collects Logon and Logout Events 110 | -w /var/log/faillog -p wa -k logins 111 | -w /var/log/lastlog -p wa -k logins 112 | #2.6.2.4.6 Ensure auditd Collects Process and Session Initiation Information 113 | -w /var/run/utmp -p wa -k session 114 | -w /var/log/btmp -p wa -k session 115 | -w /var/log/wtmp -p wa -k session 116 | #2.6.2.4.12 Ensure auditd Collects System Administrator Actions 117 | -w /etc/sudoers -p wa -k actions 118 | #2.6.2.4.13 Make the auditd Configuration Immutable 119 | -w /sbin/insmod -p x -k modules 120 | -w /sbin/rmmod -p x -k modules 121 | -w /sbin/modprobe -p x -k modules 122 | -a always,exit -F arch=b32 -S init_module -S delete_module -k modules 123 | -a always,exit -F arch=b64 -S init_module -S delete_module -k modules 124 | # Ignore all the anonymous events. Often tagged on every rule, but ignoring 125 | # up front should improve processing time 126 | -a exit,never -F auid=4294967295 127 | # Ignore system services 128 | -a exit,never -F auid<1000 129 | #2.6.2.4.7 Ensure auditd Collects Discretionary Access Control Permission Modification Events 130 | -a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -k perm_mod 131 | -a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -k perm_mod 132 | -a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -k perm_mod 133 | -a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -k perm_mod 134 | -a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -k perm_mod 135 | -a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -k perm_mod 136 | #2.6.2.4.8 Ensure auditd Collects Unauthorized Access Attempts to Files (unsuccessful) 137 | -a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -k access 138 | -a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -k access 139 | -a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -k access 140 | -a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -k access 141 | #2.6.2.4.9 Ensure auditd Collects Information on the Use of Privileged Commands 142 | -a always,exit -F path=/usr/sbin/semanage -F perm=x -F key=privileged-priv_change 143 | -a always,exit -F path=/usr/sbin/setsebool -F perm=x -F key=privileged-priv_change 144 | -a always,exit -F path=/usr/bin/chcon -F perm=x -F key=privileged-priv_change 145 | -a always,exit -F path=/usr/sbin/restorecon -F perm=x -F key=privileged-priv_change 146 | -a always,exit -F path=/usr/bin/userhelper -F perm=x -F key=privileged 147 | -a always,exit -F path=/usr/bin/sudoedit -F perm=x -F key=privileged 148 | -a always,exit -F path=/usr/libexec/pt_chown -F perm=x -F key=privileged 149 | EOF 150 | 151 | # Find all privileged commands and monitor them 152 | for fs in $(awk '($3 ~ /(ext[234])|(xfs)/) {print $2}' /proc/mounts) ; do 153 | find $fs -xdev -type f \( -perm -4000 -o -perm -2000 \) | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged" }' >> /etc/audit/rules.d/audit.rules 154 | done 155 | 156 | cat <> /etc/audit/rules.d/audit.rules 157 | #2.6.2.4.10 Ensure auditd Collects Information on Exporting to Media (successful) 158 | -a always,exit -F arch=b32 -S mount -k export 159 | -a always,exit -F arch=b64 -S mount -k export 160 | #2.6.2.4.11 Ensure auditd Collects Files Deletion Events by User (successful and unsuccessful) 161 | -a always,exit -F arch=b32 -S unlink -S rmdir -S unlinkat -S rename -S renameat -k delete 162 | -a always,exit -F arch=b64 -S unlink -S rmdir -S unlinkat -S rename -S renameat -k delete 163 | #2.6.2.4.14 Make the auditd Configuration Immutable 164 | -e 2 165 | EOF 166 | 167 | service auditd restart 168 | 169 | # Set logrotate times 170 | sed -i "s/weekly/daily/g" /etc/logrotate.conf 171 | sed -i "s/monthly/weekly/g" /etc/logrotate.conf 172 | sed -i "s/rotate 4/rotate 7/g" /etc/logrotate.conf 173 | 174 | # The current scap files reference a http link. RedHat redirects to https and oscap doesn't like that. 175 | # Replace the links using https / compressed OVAL data 176 | sed -i 's@http://www.redhat.com/security/data/oval/Red_Hat_Enterprise_Linux_7.xml@https://www.redhat.com/security/data/oval/com.redhat.rhsa-RHEL7.xml.bz2@g' /usr/share/xml/scap/ssg/content/ssg-centos7-ds.xml 177 | sed -i 's@http://www.redhat.com/security/data/oval/Red_Hat_Enterprise_Linux_7.xml@https://www.redhat.com/security/data/oval/com.redhat.rhsa-RHEL7.xml.bz2@g' /usr/share/xml/scap/ssg/content/ssg-centos7-xccdf.xml 178 | 179 | # There is currently an issue with the scap-security-guide on CentOS 7 and it's 180 | # detection and remediation of prelinking hence the || true. Prelink is not 181 | # not installed and is disabled by default even when it is installed. 182 | oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_pci-dss --fetch-remote-resources --remediate /usr/share/xml/scap/ssg/content/ssg-centos7-ds.xml || true 183 | -------------------------------------------------------------------------------- /scripts/centos7-hardened-install.sh: -------------------------------------------------------------------------------- 1 | # Installs cloudinit, cloud-init, havaged - requires epel repo 2 | yum -y install wget 3 | 4 | version=7 5 | mirror=http://mirror.bytemark.co.uk/centos/ 6 | 7 | # Detect primary root drive 8 | if [ -e /dev/xvda ]; then 9 | drive=xvda 10 | elif [ -e /dev/vda ]; then 11 | drive=vda 12 | elif [ -e /dev/sda ]; then 13 | drive=sda 14 | fi 15 | 16 | mkdir /boot/centos 17 | cd /boot/centos 18 | wget ${mirror}/${version}/os/x86_64/isolinux/vmlinuz 19 | wget ${mirror}/${version}/os/x86_64/isolinux/initrd.img 20 | 21 | 22 | # This kickstart file has been adapted from the scap-security-guide kickstart 23 | # file in: https://github.com/OpenSCAP/scap-security-guide and the RedHatGov 24 | # project: https://github.com/RedHatGov/ssg-el7-kickstart 25 | cat > /boot/centos/kickstart.ks << EOKSCONFIG 26 | # SCAP Security Guide OSPP/USGCB profile kickstart for Red Hat Enterprise Linux 7 Server 27 | # Version: 0.0.2 28 | # Date: 2015-11-19 29 | # 30 | # Based on: 31 | # http://fedoraproject.org/wiki/Anaconda/Kickstart 32 | # https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/sect-kickstart-syntax.html 33 | # http://usgcb.nist.gov/usgcb/content/configuration/workstation-ks.cfg 34 | 35 | # Text or Graphical 36 | text 37 | 38 | # Install a fresh new system (optional) 39 | install 40 | 41 | # Don't run the Setup Agent on first boot 42 | firstboot --disable 43 | 44 | # Accept Eula 45 | eula --agreed 46 | 47 | # Suppress unsupported hardware warning 48 | unsupported_hardware 49 | 50 | # Don't configure X even if installed 51 | skipx 52 | 53 | # Specify installation method to use for installation 54 | # To use a different one comment out the 'url' one below, update 55 | # the selected choice with proper options & un-comment it 56 | # 57 | # Install from an installation tree on a remote server via FTP or HTTP: 58 | # --url the URL to install from 59 | # 60 | # Example: 61 | # 62 | # url --url=http://192.168.122.1/image 63 | # 64 | # Modify concrete URL in the above example appropriately to reflect the actual 65 | # environment machine is to be installed in 66 | # 67 | # Other possible / supported installation methods: 68 | # * install from the first CD-ROM/DVD drive on the system: 69 | # 70 | # cdrom 71 | # 72 | # * install from a directory of ISO images on a local drive: 73 | # 74 | # harddrive --partition=hdb2 --dir=/tmp/install-tree 75 | # 76 | # * install from provided NFS server: 77 | # 78 | # nfs --server= --dir= [--opts=] 79 | # 80 | 81 | # We'll be using a known good mirror of CentOS repos for the install 82 | # Many thanks to ByteMark, a Manchester based ISP worth checking out 83 | url --url="http://mirror.bytemark.co.uk/centos/7/os/x86_64/" 84 | repo --name="base" --baseurl=http://mirror.bytemark.co.uk/centos/7/os/x86_64/ 85 | # Including the updates repo ensures we install the latest packages at install time 86 | repo --name="updates" --baseurl=http://mirror.bytemark.co.uk/centos/7/updates/x86_64/ 87 | repo --name="extras" --baseurl=http://mirror.bytemark.co.uk/centos/7/extras/x86_64/ 88 | repo --name="epel" --baseurl=http://mirror.bytemark.co.uk/fedora/epel/7/x86_64/ 89 | repo --name="puppet" --baseurl=https://yum.puppetlabs.com/el/7/PC1/x86_64/ 90 | 91 | # OS Locale and time 92 | lang en_GB.UTF-8 93 | keyboard uk 94 | timezone Europe/London --isUtc --ntpservers=0.centos.pool.ntp.org,1.centos.pool.ntp.org,2.centos.pool.ntp.org,3.centos.pool.ntp.org 95 | 96 | # Configure network information for target system and activate network devices in the installer environment (optional) 97 | # --onboot enable device at a boot time 98 | # --device device to be activated and / or configured with the network command 99 | # --bootproto method to obtain networking configuration for device (default dhcp) 100 | # --noipv6 disable IPv6 on this device 101 | # 102 | # NOTE: Usage of DHCP will fail CCE-27021-5 (DISA FSO RHEL-06-000292). To use static IP configuration, 103 | # "--bootproto=static" must be used. For example: 104 | # network --bootproto=static --ip=10.0.2.15 --netmask=255.255.255.0 --gateway=10.0.2.254 --nameserver 192.168.2.1,192.168.3.1 105 | # 106 | network --onboot yes --device eth0 --bootproto dhcp --ipv6=auto --activate 107 | 108 | # Set the system's root password (required) 109 | rootpw --lock --iscrypted "*" 110 | 111 | # Configure firewall settings for the system (optional) 112 | # --enabled reject incoming connections that are not in response to outbound requests 113 | # --ssh allow sshd service through the firewall 114 | firewall --enabled --ssh 115 | 116 | # Set up the authentication options for the system (required) 117 | # --enableshadow enable shadowed passwords by default 118 | # --passalgo hash / crypt algorithm for new passwords 119 | # See the manual page for authconfig for a complete list of possible options. 120 | authconfig --enableshadow --passalgo=sha512 121 | 122 | # State of SELinux on the installed system (optional) 123 | # Defaults to enforcing 124 | selinux --enforcing 125 | 126 | # Specify how the bootloader should be installed (required) 127 | bootloader --location=mbr --append="crashkernel=auto rhgb quiet" --timeout=0 128 | 129 | # Initialize (format) all disks (optional) 130 | zerombr 131 | 132 | # The following partition layout scheme assumes disk of size 20GB or larger 133 | # Modify size of partitions appropriately to reflect actual machine's hardware 134 | # 135 | # Remove Linux partitions from the system prior to creating new ones (optional) 136 | # --linux erase all Linux partitions 137 | # --initlabel initialize the disk label to the default based on the underlying architecture 138 | clearpart --linux --initlabel 139 | 140 | # Create primary system partitions (required for installs) 141 | part /boot --fstype=xfs --size=512 142 | part pv.00 --grow --size=1 143 | 144 | # Create a Logical Volume Management (LVM) group (optional) 145 | volgroup VolGroup00 --pesize=4096 pv.00 146 | 147 | # Create particular logical volumes (optional) 148 | logvol / --fstype=xfs --name=00_root --vgname=VolGroup00 --size=256 --fsoptions="defaults,nobarrier,noatime,nodiratime" 149 | # CCE-26557-9: Ensure /home Located On Separate Partition 150 | logvol /home --fstype=xfs --name=01_home --vgname=VolGroup00 --size=1024 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev" 151 | # CCE-26435-8: Ensure /tmp Located On Separate Partition 152 | logvol /tmp --fstype=xfs --name=02_tmp --vgname=VolGroup00 --size=256 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev,noexec,nosuid" 153 | # CCE-26639-5: Ensure /var Located On Separate Partition 154 | logvol /var --fstype=xfs --name=03_var --vgname=VolGroup00 --size=512 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev" 155 | logvol /var/tmp --fstype=xfs --name=04_var_tmp --vgname=VolGroup00 --size=256 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev,noexec,nosuid" 156 | # CCE-26215-4: Ensure /var/log Located On Separate Partition 157 | logvol /var/log --fstype=xfs --name=05_var_log --vgname=VolGroup00 --size=256 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev" 158 | # CCE-26436-6: Ensure /var/log/audit Located On Separate Partition 159 | logvol /var/log/audit --fstype=xfs --name=06_var_log_audit --vgname=VolGroup00 --size=256 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev" 160 | 161 | # Usually where applications get put to run 162 | logvol /opt --fstype=xfs --name=07_opt --vgname=VolGroup00 --size=512 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev" 163 | logvol /usr --fstype=xfs --name=08_usr --vgname=VolGroup00 --size=1536 --fsoptions="defaults,nobarrier,noatime,nodiratime,nodev" 164 | 165 | # Very small swap - we usually set swap to 1 for safety 166 | logvol swap --name=lv_swap --vgname=VolGroup00 --size=128 167 | 168 | # Service configuration 169 | services --enabled=NetworkManager,sshd,chronyd,tuned,haveged 170 | 171 | # Packages selection (%packages section is required) 172 | %packages --excludedocs 173 | 174 | # Install ther latest security guide packege 175 | scap-security-guide 176 | 177 | # CCE-27024-9: Install AIDE 178 | aide 179 | 180 | # Install libreswan package 181 | libreswan 182 | 183 | # A selection of basic system packages 184 | @core 185 | chrony 186 | yum-utils 187 | system-config-firewall-base 188 | wget 189 | 190 | # tuned is great for the cloud / virtual world 191 | tuned 192 | 193 | # Cloud init bootstraps instances based on this AMI 194 | cloud-init 195 | 196 | # havaged improves entropy in the virtual world 197 | haveged 198 | 199 | # unneeded firmware 200 | -aic94xx-firmware 201 | -atmel-firmware 202 | -b43-openfwwf 203 | -bfa-firmware 204 | -ipw2100-firmware 205 | -ipw2200-firmware 206 | -ivtv-firmware 207 | -iwl100-firmware 208 | -iwl1000-firmware 209 | -iwl3945-firmware 210 | -iwl4965-firmware 211 | -iwl5000-firmware 212 | -iwl5150-firmware 213 | -iwl6000-firmware 214 | -iwl6000g2a-firmware 215 | -iwl6050-firmware 216 | -libertas-usb8388-firmware 217 | -ql2100-firmware 218 | -ql2200-firmware 219 | -ql23xx-firmware 220 | -ql2400-firmware 221 | -ql2500-firmware 222 | -rt61pci-firmware 223 | -rt73usb-firmware 224 | -xorg-x11-drv-ati-firmware 225 | -zd1211-firmware 226 | 227 | # Disable prelink by not installing it 228 | -prelink 229 | %end 230 | 231 | # We can apply most security config at install time with the kickstart addon 232 | %addon org_fedora_oscap 233 | content-type = scap-security-guide 234 | profile = pci-dss 235 | %end 236 | 237 | # A bit of cleanup post install 238 | %post 239 | # cloud-init config 240 | mkdir -p /etc/cloud/ 241 | echo "--- 242 | users: 243 | - default 244 | 245 | preserve_hostname: false 246 | 247 | # This is our pre-base image. Update packages. 248 | package_update: true 249 | package_reboot_if_required: true 250 | 251 | # We're in the UK so let's accept it. 252 | locale_configfile: /etc/sysconfig/i18n 253 | locale: en_GB.UTF-8 254 | timezone: Europe/London 255 | 256 | # SSH Configuration 257 | disable_root: true 258 | ssh_pwauth: no 259 | ssh_deletekeys: true 260 | ssh_genkeytypes: ~ 261 | 262 | syslog_fix_perms: ~ 263 | 264 | system_info: 265 | default_user: 266 | name: centos 267 | lock_passwd: false 268 | # password: centos 269 | passwd: $6$Uq.eaVbT3$mNtmpx.3bMPN/DuMs8BjRMCIrFzpglPPw2cf9TvjOU6mD4jav3NOGWQpHX8jF.IIiMhbTEve.zOsD7o6RXVB.1 270 | gecos: Administrator 271 | groups: [wheel, adm, systemd-journal] 272 | sudo: ["ALL=(ALL) NOPASSWD:ALL"] 273 | shell: /bin/bash 274 | distro: rhel 275 | paths: 276 | cloud_dir: /var/lib/cloud 277 | templates_dir: /etc/cloud/templates 278 | ssh_svcname: sshd 279 | 280 | # Edit these to our taste 281 | cloud_init_modules: 282 | - migrator 283 | - bootcmd 284 | - write-files 285 | - growpart 286 | - resizefs 287 | - set_hostname 288 | - update_hostname 289 | - update_etc_hosts 290 | - rsyslog 291 | - users-groups 292 | - ssh 293 | 294 | cloud_config_modules: 295 | - mounts 296 | - locale 297 | - set-passwords 298 | - yum-add-repo 299 | - package-update-upgrade-install 300 | - timezone 301 | - puppet 302 | - chef 303 | - salt-minion 304 | - mcollective 305 | - disable-ec2-metadata 306 | - runcmd 307 | 308 | cloud_final_modules: 309 | - rightscale_userdata 310 | - scripts-per-once 311 | - scripts-per-boot 312 | - scripts-per-instance 313 | - scripts-user 314 | - ssh-authkey-fingerprints 315 | - keys-to-console 316 | - phone-home 317 | - final-message 318 | " > /etc/cloud/cloud.cfg 319 | 320 | # Cleanup SSH keys 321 | rm -f /etc/ssh/*key* 322 | rm -rf ~/.ssh/ 323 | 324 | # Don't require tty for ssh / sudo 325 | sed -i "s/^.*requiretty/#Defaults requiretty/" /etc/sudoers 326 | 327 | # Run the virtual-guest tuned profile 328 | echo "virtual-guest" > /etc/tune-profiles/active-profile 329 | 330 | # Let SELinux relabel FS on next boot 331 | touch /.autorelabel 332 | %end 333 | reboot --eject 334 | EOKSCONFIG 335 | 336 | echo "menuentry 'centosinstall' { 337 | set root='hd0,msdos1' 338 | linux /boot/centos/vmlinuz ip=dhcp ksdevice=eth0 ks=hd:${drive}1:/boot/centos/kickstart.ks method=${mirror}/${version}/os/x86_64/ lang=en_US keymap=us 339 | initrd /boot/centos/initrd.img 340 | }" >> /etc/grub.d/40_custom 341 | 342 | echo 'GRUB_DEFAULT=saved 343 | GRUB_HIDDEN_TIMEOUT= 344 | GRUB_TIMEOUT=2 345 | GRUB_RECORDFAIL_TIMEOUT=5 346 | GRUB_CMDLINE_LINUX_DEFAULT="quiet nosplash vga=771 nomodeset" 347 | GRUB_DISABLE_LINUX_UUID=true' > /etc/default/grub 348 | 349 | grub2-set-default 'centosinstall' 350 | grub2-mkconfig -o /boot/grub2/grub.cfg 351 | 352 | rm -rf ~/.ssh/* 353 | rm -rf /root/* 354 | 355 | reboot 356 | --------------------------------------------------------------------------------