diff --git a/.gitignore b/.gitignore index fbe87e0..1953eaa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,3 @@ -README.pdf -README.html -shared_test_repo/ -test/integration .kitchen -coverage -Vagrantfile.erb - -Gemfile.lock -Berksfile.lock - -ansible.cfg hosts +Gemfile.lock diff --git a/.kitchen.vagrant.yml b/.kitchen.vagrant.yml new file mode 100644 index 0000000..23b1614 --- /dev/null +++ b/.kitchen.vagrant.yml @@ -0,0 +1,38 @@ +--- +driver: + name: vagrant + +provisioner: + name: ansible_playbook + hosts: all + require_ansible_repo: false + require_ansible_omnibus: true + require_chef_for_busser: false + require_ruby_for_busser: false + ansible_verbose: true + roles_path: ../ansible-mysql-hardening/ + playbook: default.yml + requirements_path: requirements.yml + sudo_command: 'sudo -E -H' + +transport: + max_ssh_sessions: 5 + +platforms: +- name: ubuntu-14.04 +- name: ubuntu-16.04 +- name: centos-6.8 +- name: centos-7.3 +- name: oracle-6.8 +- name: oracle-7.3 +- name: debian-7.11 +- name: debian-8.7 + +verifier: + name: inspec + sudo: true + inspec_tests: + - https://github.com/dev-sec/mysql-baseline/ + +suites: +- name: mysql diff --git a/.kitchen.yml b/.kitchen.yml index 0b2054e..0d3a4d8 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -1,62 +1,77 @@ --- driver: - name: vagrant + name: docker + privileged: true + use_sudo: false + +transport: + max_ssh_sessions: 5 + provisioner: name: ansible_playbook - test_repo_uri: https://github.com/hardening-io/tests-mysql-hardening.git hosts: all - playbook: default.yml require_ansible_repo: false require_ansible_omnibus: true - requirements_path: requirements.yml + require_chef_for_busser: false + require_ruby_for_busser: false ansible_verbose: true ansible_diff: true + hosts: all roles_path: ../ansible-mysql-hardening/ + playbook: default.yml + requirements_path: requirements.yml sudo_command: 'sudo -E -H' platforms: -- name: ubuntu-12.04 - driver_config: - box: opscode-ubuntu-12.04 - box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-12.04_chef-provisionerless.box -- name: ubuntu-14.04 - driver_config: - box: opscode-ubuntu-14.04 - box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box -- name: centos-6.4 - driver_config: - box: opscode-centos-6.4 - box_url: https://opscode-vm.s3.amazonaws.com/vagrant/opscode_centos-6.4_provisionerless.box -- name: centos-6.5 - driver_config: - box: opscode-centos-6.5 - box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box -- name: centos-7.2 - driver_config: - box: opscode-centos-7.2 - box_url: http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-7.2_chef-provisionerless.box -- name: oracle-6.4 - driver_config: - box: oracle-6.4 - box_url: https://storage.us2.oraclecloud.com/v1/istoilis-istoilis/vagrant/oel64-64.box -- name: oracle-6.5 - driver_config: - box: oracle-6.5 - box_url: https://storage.us2.oraclecloud.com/v1/istoilis-istoilis/vagrant/oel65-64.box -- name: debian-6 - driver_config: - box: debian-6 - box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-6.0.10_chef-provisionerless.box -- name: debian-7 - driver_config: - box: debian-7 - box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8_chef-provisionerless.box -- name: debian-8 - driver_config: - box: debian-8 - box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-8.1_chef-provisionerless.box +- name: centos6-ansible-latest + driver: + image: rndmh3ro/docker-centos6-ansible:latest + platform: centos +- name: centos7-ansible-latest + driver: + image: rndmh3ro/docker-centos7-ansible:latest + platform: centos +- name: oracle6-ansible-latest + driver: + image: rndmh3ro/docker-oracle6-ansible:latest + platform: centos +- name: oracle7-ansible-latest + driver: + image: rndmh3ro/docker-oracle7-ansible:latest + platform: centos +- name: ubuntu1404-ansible-latest + driver: + image: rndmh3ro/docker-ubuntu1404-ansible:latest + platform: ubuntu +- name: ubuntu1604-ansible-latest + driver: + image: rndmh3ro/docker-ubuntu1604-ansible:latest + platform: ubuntu +- name: debian7-ansible-latest + driver: + image: rndmh3ro/docker-debian7-ansible:latest + platform: debian + intermediate_instructions: + - RUN /usr/bin/apt-get update + - RUN /usr/bin/apt-get install -y procps +- name: debian8-ansible-latest + driver: + image: rndmh3ro/docker-debian8-ansible:latest + platform: debian + intermediate_instructions: + - RUN /usr/bin/apt-get update + - RUN /usr/bin/apt-get install -y procps + pid_one_command: /bin/systemd +- name: debian9-ansible-latest + driver: + image: rndmh3ro/docker-debian9-ansible:latest + platform: debian + +verifier: + name: inspec + sudo: true + inspec_tests: + - https://github.com/dev-sec/mysql-baseline + suites: -- name: ansible_1.9 - provisioner: - ansible_version: 1.9.4 -- name: ansible_latest +- name: mysql diff --git a/.travis.yml b/.travis.yml index 48e33a0..5c8747f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,75 @@ --- -notifications: - webhooks: https://galaxy.ansible.com/api/v1/notifications/ -language: python -python: "2.7" +services: docker env: - - ANSIBLE_VERSION=latest - - ANSIBLE_VERSION=1.9.4 + - distro: centos6 + version: latest + run_opts: "--privileged" + init: /sbin/init + + - distro: centos7 + init: /usr/lib/systemd/systemd + run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro" + version: latest + + - distro: oracle6 + version: latest + run_opts: "--privileged" + init: /sbin/init + + - distro: oracle7 + init: /usr/lib/systemd/systemd + run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro" + version: latest + +# see https://github.com/dev-sec/mysql-baseline/issues/35 +# - distro: ubuntu1604 +# version: latest +# init: /lib/systemd/systemd +# run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro" + +# - distro: ubuntu1404 +# version: latest +# run_opts: "--privileged" +# init: /sbin/init + + - distro: debian7 + version: latest + run_opts: "--privileged" + init: /sbin/init + +# - distro: debian8 +# version: latest +# init: /bin/systemd +# run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro" + + # - distro: debian9 + # version: latest + # init: /lib/systemd/systemd + # run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro" before_install: - - sudo apt-get update -qq - - sudo apt-get install -qq python-apt python-pycurl python-mysqldb -install: - - if [ "$ANSIBLE_VERSION" = "latest" ]; then pip install ansible; else pip install ansible==$ANSIBLE_VERSION; fi - - echo -e 'localhost ansible_connection=local' > spec/inventory - - echo -e '[defaults]\nroles_path = ../\nhostfile = ./spec/inventory' > ansible.cfg + # Pull container + - 'docker pull rndmh3ro/docker-${distro}-ansible:${version}' script: - - ansible-playbook --syntax-check spec/travis.yml - - ansible-playbook --sudo -v --diff spec/travis.yml + - container_id=$(mktemp) + # Run container in detached state. + - 'docker run --detach --volume="${PWD}":/etc/ansible/roles/ansible-mysql-hardening:ro ${run_opts} rndmh3ro/docker-${distro}-ansible:${version} "${init}" > "${container_id}"' + + # Install ansible galaxy requirements + - 'docker exec "$(cat ${container_id})" ansible-galaxy install -r /etc/ansible/roles/ansible-mysql-hardening/requirements.yml -p /etc/ansible/roles/' + + # Test role. + - 'travis_wait docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/ansible-mysql-hardening/default.yml' + + # Verify role + - 'inspec exec https://github.com/rndmh3ro/mysql-baseline/ -t docker://$(cat ${container_id})' + +after_failure: + # Check MySQL settings. + - 'docker exec --tty ${container_id} env TERM=xterm cat /var/log/mysql/error.log' + - 'docker exec --tty ${container_id} env TERM=xterm cat /var/log/mysql.err' + - 'docker exec --tty ${container_id} env TERM=xterm cat /var/log/mysql.log' +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ diff --git a/Gemfile b/Gemfile index 4dfd9cf..c11b3bf 100644 --- a/Gemfile +++ b/Gemfile @@ -2,32 +2,15 @@ source 'https://rubygems.org' -group :test do - gem 'rake' -# gem 'chefspec', '~> 4.2.0' - gem 'foodcritic', '~> 4.0' - gem 'thor-foodcritic' -# gem 'rubocop', '~> 0.28.0' - gem 'coveralls', require: false -end - -group :development do - gem 'guard' - gem 'guard-rspec' - gem 'guard-kitchen' -# gem 'guard-rubocop' -# gem 'guard-foodcritic' -end - group :integration do gem 'test-kitchen', '~> 1.0' gem 'kitchen-ansible' gem 'kitchen-vagrant' + gem 'kitchen-inspec' gem 'kitchen-sharedtests', '~> 0.2.0' -end - -group :openstack do - gem 'kitchen-openstack' + gem 'kitchen-sync' + gem 'kitchen-transport-rsync' + gem 'kitchen-docker' end group :tools do diff --git a/README.md b/README.md index ec27898..020623e 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,9 @@ Further information is already available at [Deutsche Telekom (German)](http://w ## Local Testing -For local testing you can use vagrant and Virtualbox of VMWare to run tests locally. You will have to install Virtualbox and Vagrant on your system. See [Vagrant Downloads](http://downloads.vagrantup.com/) for a vagrant package suitable for your system. For all our tests we use `test-kitchen`. If you are not familiar with `test-kitchen` please have a look at [their guide](http://kitchen.ci/docs/getting-started). +The preferred way of locally testing the role is to use Docker. You will have to install Docker on your system. See [Get started](https://docs.docker.com/) for a Docker package suitable to for your system. + +You can also use vagrant and Virtualbox or VMWare to run tests locally. You will have to install Virtualbox and Vagrant on your system. See [Vagrant Downloads](http://downloads.vagrantup.com/) for a vagrant package suitable for your system. For all our tests we use `test-kitchen`. If you are not familiar with `test-kitchen` please have a look at [their guide](http://kitchen.ci/docs/getting-started). Next install test-kitchen: @@ -58,16 +60,10 @@ Next install test-kitchen: # Install dependencies gem install bundler bundle install +``` -# Fetch tests -bundle exec thor kitchen:fetch-remote-tests - -# download a MySQL-installation role -ansible-galaxy install -p roles/ bennojoy.mysql - -# change password in MySQL-installation role to match the one from testing -sed -i 's/foobar/iloverandompasswordsbutthiswilldo/g' roles/bennojoy.mysql/defaults/main.yml - +### Testing with Docker +``` # fast test on one machine bundle exec kitchen test default-ubuntu-1204 @@ -79,8 +75,19 @@ bundle exec kitchen create default-ubuntu-1204 bundle exec kitchen converge default-ubuntu-1204 ``` -For more information see [test-kitchen](http://kitchen.ci/docs/getting-started) +### Testing with Virtualbox +``` +# fast test on one machine +KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen test default-ubuntu-1404 + +# test on all machines +KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen test +# for development +KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen create default-ubuntu-1404 +KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen converge default-ubuntu-1404 +``` +For more information see [test-kitchen](http://kitchen.ci/docs/getting-started) ## License and Author diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 8b13789..0000000 --- a/TODO.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Thorfile b/Thorfile deleted file mode 100644 index 15b092f..0000000 --- a/Thorfile +++ /dev/null @@ -1,10 +0,0 @@ -# encoding: utf-8 - -require 'bundler' -require 'bundler/setup' -require 'thor/foodcritic' - -require 'kitchen_sharedtests' -require 'kitchen/sharedtests_thor_tasks' - -Kitchen::SharedtestsThorTasks.new diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..d7cda5b --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,14 @@ +# config file for ansible -- http://ansible.com/ +# ============================================== + +# nearly all parameters can be overridden in ansible-playbook +# or with command line flags. ansible will read ANSIBLE_CONFIG, +# ansible.cfg in the current working directory, .ansible.cfg in +# the home directory or /etc/ansible/ansible.cfg, whichever it +# finds first + +[defaults] +ansible_managed = Ansible managed: {file} modified on %Y-%m-%d by {uid} on {host} + +role_path = /vagrant +scp_if_ssh = True diff --git a/default.yml b/default.yml index ce4b72b..6518641 100644 --- a/default.yml +++ b/default.yml @@ -1,9 +1,26 @@ --- + - name: wrapper playbook for kitchen testing "ansible-mysql-hardening" hosts: localhost + pre_tasks: + - file: path="/etc/mysql" state=directory + - name: Copy initctl_faker into place for Ubuntu 14.04. + copy: + src: initctl_faker + dest: /sbin/initctl + mode: 0755 + force: yes + when: ansible_distribution == 'Ubuntu' and ansible_distribution_version == '14.04' + changed_when: false + - name: install procps for debian systems + apt: name=procps state=installed update_cache=yes + when: ansible_distribution == 'Debian' vars: overwrite_global_mycnf: no - mysql_root_password: "root" + mysql_root_password: iloverandompasswordsbutthiswilldo + mysql_user_password: iloverandompasswordsbutthiswilldo + mysql_config_file: /etc/mysql/mariadb.cnf + mysql_root_password_update: yes roles: - geerlingguy.mysql - ansible-mysql-hardening diff --git a/defaults/main.yml b/defaults/main.yml index a2a87f4..1d4dba2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -2,13 +2,14 @@ mysql_hardening_enabled: yes # general configuration -mysql_hardening_user: 'mysql' +mysql_cnf_owner: 'root' # owner of /etc/mysql/*.cnf files +mysql_hardening_user: 'mysql' # owner of data mysql_hardening_group: 'root' mysql_datadir: '/var/lib/mysql' mysql_hardening_mysql_hardening_conf_file: '{{mysql_hardening_mysql_confd_dir}}/hardening.cnf' # You have to change this to your own strong enough mysql root password mysql_root_password: '-----====>SetR00tPa$$wordH3r3!!!<====-----' -# There .my.cnf with mysql root credentials will be installed +# There .my.cnf with mysql root credentials will be installed mysql_user_home: "{{ ansible_env.HOME}}" # ensure the following parameters are set properly @@ -47,3 +48,5 @@ mysql_hardening_options: # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option-mysqld-secure-file-priv secure-file-priv: '/tmp' + # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_user + user: '{{mysql_hardening_user}}' diff --git a/initctl_faker b/initctl_faker new file mode 100644 index 0000000..55d2c36 --- /dev/null +++ b/initctl_faker @@ -0,0 +1,24 @@ +#!/bin/sh +ALIAS_CMD="$(echo ""$0"" | sed -e 's?/sbin/??')" + +case "$ALIAS_CMD" in + start|stop|restart|reload|status) + exec service $1 $ALIAS_CMD + ;; +esac + +case "$1" in + list ) + exec service --status-all + ;; + reload-configuration ) + exec service $2 restart + ;; + start|stop|restart|reload|status) + exec service $2 $1 + ;; + \?) + exit 0 + ;; +esac + diff --git a/spec/travis.yml b/spec/travis.yml deleted file mode 100644 index a307e67..0000000 --- a/spec/travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -- hosts: localhost - roles: - - ansible-mysql-hardening diff --git a/tasks/configure.yml b/tasks/configure.yml index e0b8edb..2ff0cb3 100644 --- a/tasks/configure.yml +++ b/tasks/configure.yml @@ -1,7 +1,7 @@ --- - name: protect my.cnf - file: path='{{mysql_hardening_mysql_conf_file}}' mode=0400 owner='{{mysql_hardening_user}}' group='{{mysql_hardening_group}}' follow=yes + file: path='{{mysql_hardening_mysql_conf_file}}' mode=0400 owner='{{mysql_cnf_owner}}' group='{{mysql_hardening_group}}' follow=yes state=file - name: ensure permissions on mysql-datadir are correct file: path='{{mysql_datadir}}' state=directory owner='{{mysql_hardening_user}}' group='{{mysql_hardening_user}}' @@ -14,5 +14,8 @@ notify: restart mysql - name: apply hardening configuration - template: src='hardening.cnf.j2' dest='{{mysql_hardening_mysql_hardening_conf_file}}' owner='{{mysql_hardening_user}}' group='{{mysql_hardening_group}}' mode=0460 + template: src='hardening.cnf.j2' dest='{{mysql_hardening_mysql_hardening_conf_file}}' owner='{{mysql_cnf_owner}}' group='{{mysql_hardening_group}}' mode=0460 notify: restart mysql + +- name: enable mysql + service: name='{{ mysql_daemon }}' enabled=yes diff --git a/tasks/main.yml b/tasks/main.yml index ec5ad75..330ac2e 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -11,11 +11,11 @@ - include: configure.yml when: mysql_hardening_enabled - tags: + tags: - mysql_hardening - include: mysql_secure_installation.yml when: mysql_hardening_enabled - tags: + tags: - mysql_hardening - mysql_secure_installation diff --git a/tasks/mysql_secure_installation.yml b/tasks/mysql_secure_installation.yml index d5f8834..746b142 100644 --- a/tasks/mysql_secure_installation.yml +++ b/tasks/mysql_secure_installation.yml @@ -24,7 +24,7 @@ - 'localhost' - name: install .my.cnf with credentials - template: src=my.cnf.j2 dest={{mysql_user_home}}/.my.cnf + template: src=my.cnf.j2 dest={{mysql_user_home}}/.my.cnf mode=0400 tags: my_cnf @@ -32,24 +32,9 @@ mysql_db: name=test state=absent when: mysql_remove_test_database -# Can use only if ansible ver => 2.1 -#- name: anonymous users are absent -# mysql_user: name='' state=absent host_all=yes -# when: mysql_remove_anonymous_users - -- name: copy mysql_remove_anonymous_users - copy: src='{{item}}.sql' dest='/tmp/{{item}}.sql' - with_items: - - mysql_remove_anonymous_users - when: mysql_remove_anonymous_users - changed_when: false - -- name: apply mysql_remove_anonymous_users - mysql_db: name='mysql' state=import target='/tmp/{{item}}.sql' - with_items: - - mysql_remove_anonymous_users +- name: anonymous users are absent + mysql_user: name='' state=absent host_all=yes when: mysql_remove_anonymous_users - changed_when: false - name: copy mysql_remove_remote_root copy: src='{{item}}.sql' dest='/tmp/{{item}}.sql' @@ -59,7 +44,7 @@ changed_when: false - name: apply mysql_remove_remote_root - mysql_db: name='mysql' state=import target='/tmp/{{item}}.sql' + mysql_db: name='mysql' state=import target='/tmp/{{item}}.sql' with_items: - mysql_remove_remote_root when: mysql_remove_remote_root