63
blue-bag ANSIBLE & DRUPAL MEDICINE SHOW DRUPAL BRIGHTON CAMP JANUARY 2015 GEORGE BOOBYER BLUE-BAG

Drupal Camp Brighton 2015: Ansible Drupal Medicine show

Embed Size (px)

Citation preview

Page 1: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE &

DRUPALMEDICINE SHOW

DRUPAL BRIGHTON CAMP JANUARY 2015

GEORGE BOOBYER BLUE-BAG

Page 2: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BLUE-BAG

GEORGE BOOBYER DRUPAL: [email protected] TWITTER: iBLUEBAG

www.blue-bag.com

Established in 2000The year before Drupal 1.0

Page 3: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE & DRUPAL

Security issues

Ansible

Server security

Drupal

Take homes

Questions

Page 4: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE & DRUPAL: TOP 10

1. Docker 2. Kubernetes 3. Taiga 4. Apache Mesos 5. OpenStack 6. Ansible 7. ownCloud 8. Apache Hadoop 9. Drupal 10.OpenDaylight

http://opensource.com/business/14/12/top-10-open-source-projects-2014

Top 10 open source projects in 2014

Page 5: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

SECURITY ISSUES: 2014 TRENDS

CVE-2014-0160CVE-2014-3566CVE-2014-8730

CVE-2014-6277CVE-2014-6278CVE-2014-7169CVE-2014-7186CVE-2014-7187

Shellshock Poodle Heartbleed

SSLv3Bash OpenSSL

Exploits get branding!

Page 6: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

SECURITY ISSUES: SAFE ENOUGH?Availability of cloud servers

Ease of setup

Lack of security practices

Manual exploits

Constellations of compromised machines THAT SHOULD DO IT!

Page 7: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITYPrinciple of least privilege

Limit all ports access / iptables

WAF / Appliances

Platform / Providers

Secure as soon as IP is public: First 5

Page 8: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS

Agentless Uses SSH YAML for configuration Modules Open source not just provisioning

“Ansible is a radically simple IT automation system. It handles configuration-management, application deployment, cloud provisioning, ad-hoc task-execution, and multinode orchestration.

Page 9: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE GOALS

Don’t log into servers

no need for bash scripts

Document build and configuration(in source control)

Idempotent (idem-what’s-that-again?)

Maintain configuration across inventory

Retain knowledge

Page 10: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

GET THE BOOK!33% DISCOUNT FOR DCB!http://leanpub.com/ansible-for-devops/c/VbhTIPZqGvWT !

https://leanpub.com/ansible-for-devops

Page 11: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE DOCUMENTATION

Github - https://github.com/ansible/ansibleCode and examples

Ansible Documentation - http://docs.ansible.com/ !Ansible best practiceshttp://docs.ansible.com/playbooks_best_practices.html !Ansible Galaxy - https://galaxy.ansible.com

Page 12: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS

Inventory

Commands / Modules

Roles

Tasks

Templates

Facts

Vars

Host Vars

Group vars

Handlers

Tests

Page 13: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS: MODULES

Command

Shell

Lineinfile

File

Copy

Unarchive

Apt / Yum

apache2_module

htpasswd

Git

Cloud

Homebrew

Page 14: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE / VAGRANT"## demo   "## Vagrantfile   %## hosts

# -*- mode: ruby -*-# vi: set ft=ruby :!VAGRANTFILE_API_VERSION = "2"!Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.ssh.insert_key = false config.vm.provider :virtualbox do |vb| vb.customize ["modifyvm", :id, "--memory", "256"] end ! # Application server 1. config.vm.define "app1" do |app| app.vm.hostname = "bbdemo-app1.dev" app.vm.box = "chef/debian-7.4" app.vm.network :private_network, ip: "192.168.100.120" end! # Application server 2. config.vm.define "app2" do |app| app.vm.hostname = "bbdemo-app2.dev" app.vm.box = "chef/debian-7.4" app.vm.network :private_network, ip: "192.168.100.121" end! # Database server. config.vm.define "db" do |db| db.vm.hostname = "bbdemo-db.dev" db.vm.box = "chef/debian-7.4" db.vm.network :private_network, ip: "192.168.100.122" endend

# Application servers[app]192.168.100.120192.168.100.121!# Database server[db] 192.168.100.122!# Group 'multi' with all servers[multi:children]appdb!# Variables that will be applied to all servers"[multi:vars] ansible_ssh_user=vagrantansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key

Page 15: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS$ ansible multi -i hosts -a "free -m" -u vagrant

192.168.100.121 | success | rc=0 >> total used free shared buffers cachedMem: 244 74 170 0 6 34-/+ buffers/cache: 32 212Swap: 767 0 767!192.168.100.120 | success | rc=0 >> total used free shared buffers cachedMem: 244 74 170 0 6 34-/+ buffers/cache: 32 212Swap: 767 0 767!192.168.100.122 | success | rc=0 >> total used free shared buffers cachedMem: 244 74 170 0 6 34-/+ buffers/cache: 32 212Swap: 767 0 767

Page 16: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS"## demo   "## Vagrantfile   "## ansible.cfg   "## hosts   %## log %## ansible.log

[defaults]log_path = log/ansible.loghostfile = ./hosts

…[multi]ansible_ssh_user=vagrant…

$ansible multi -i hosts -a "free -m" -u vagrant

Page 17: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS

$ ansible multi -a “date"!

192.168.100.122 | success | rc=0 >>Tue Jan 13 10:14:15 UTC 2015!

192.168.100.121 | success | rc=0 >>Tue Jan 13 10:14:15 UTC 2015!

192.168.100.120 | success | rc=0 >>Tue Jan 13 10:14:15 UTC 2015

Page 18: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS$ansible multi -s -m apt -a "pkg=ntp state=installed_ update_cache=yes"192.168.100.121 | success >> { "changed": true, "stderr": "", "stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nThe following extra packages will be installed:\n libopts25\nSuggested packages:\n ntp-doc\nThe following NEW packages will be installed:\n libopts25 ntp\n0 upgraded, 2 newly installed, 0 to remove and 72 not upgraded.\nNeed to get 565 kB/638 kB of archives.\nAfter this operation, 1364 kB of additional disk space will be used.\nGet:1 http://mirrors.kernel.org/debian/ wheezy/main ntp amd64 1:4.2.6.p5+dfsg-2+deb7u1 [565 kB]\nFetched 565 kB in 13s (40.8 kB/s)\nSelecting previously unselected package libopts25.\r\n(Reading database ... \r(Reading database ... 5%\r(Reading database ... 10%\r(Reading database ... 15%\r(Reading database ... 20%\r(Reading database ... 25%\r(Reading database ... 30%\r(Reading database ... 35%\r(Reading database ... 40%\r(Reading database ... 45%\r(Reading database ... 50%\r(Reading database ... 55%\r(Reading database ... 60%\r(Reading database ... 65%\r(Reading database ... 70%\r(Reading database ... 75%\r(Reading database ... 80%\r(Reading database ... 85%\r(Reading database ... 90%\r(Reading database ... 95%\r(Reading database ... 100%\r(Reading database ... 37414 files and directories currently installed.)\r\nUnpacking libopts25 (from .../libopts25_1%3a5.12-0.1_amd64.deb) ...\r\nSelecting previously unselected package ntp.\r\nUnpacking ntp (from .../ntp_1%3a4.2.6.p5+dfsg-2+deb7u1_amd64.deb) ...\r\nProcessing triggers for man-db ...\r\nSetting up libopts25 (1:5.12-0.1) ...\r\nSetting up ntp (1:4.2.6.p5+dfsg-2+deb7u1) ...\r\nStarting NTP server: ntpd.\r\n"}

Page 19: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS: THE PLAYBOOK

--- - hosts: all gather_facts: true sudo: true tasks: - name: NTP | Install NTP apt: > name=ntp state=installed update_cache=yes cache_valid_time=3600

"## demo   "## Vagrantfile   "## ansible.cfg   "## hosts   %## log %## ansible.log "## playbook.yml

$ ansible-playbook playbook.yml

http://docs.ansible.com/apt_module.html

Page 20: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS: ROLES

$ansible-galaxy init 'myrole'

"## myrole   "## README.md   "## defaults   &   %## main.yml   "## files   "## handlers   &   %## main.yml   "## meta   &   %## main.yml   "## tasks   &   %## main.yml   "## templates   %## vars   %## main.yml

Use Galaxy Init to create roles

Page 21: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS: PROJECT STRUCTURE

https://github.com/iAugur/ansible-playbook-template

"## LICENSE"## README.md"## ansible.cfg"## common&   "## handlers&   &   %## main.yml&   %## vars&   %## main.yml"## group_vars&   %## all.yml"## host_vars&   %## local.yml"## hosts"## log"## playbook.yml"## roles   %## base   "## README.md   "## defaults   &   %## main.yml   "## files   "## handlers   &   %## main.yml   "## meta  &   %## main.yml  "## tasks  &   %## main.yml  "## templates  %## vars   %## main.yml

Use a template for Ansible projects.

Common structure

Page 22: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS: TESTING

Test play books$ ansible-playbook --syntax-check --list-tasks main.yml

Check mode$ansible-playbook main.yml --check $ansible-playbook main.yml --check --diff

Test against Virtual machines$ ansible-playbook main.yml -l local

Page 23: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: FIRST 5Lock down SSH

Create users and groups

Limit SSH to RSA key: (no passwords / no root)Limit to AllowGroups

Update APT - unattended updates security

Configure hostname

Configure IPTables

Configure Fail2ban

Page 24: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: FIRST 5Take what we know

Research

Create templates / vars

Consistent across infrastructure

Use tasks to implement

Idempotent

Version controlled

Documented

Page 25: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

FIRST5: SSH - EXAMPLE"## README.md"## tasks&   "## main.yml&   %## ssh_config.yml"## templates&   %## ssh_config.j2%## vars %## main.yml

Page 26: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

FIRST5: SSH - EXAMPLE"## README.md"## tasks&   "## main.yml&   %## ssh_config.yml"## templates&   %## ssh_config.j2%## vars %## main.yml

# Package generated configuration file# See the sshd_config(5) manpage for details!# What ports, IPs and protocols we listen forPort 22# Use these options to restrict which interfaces/protocols sshd will bind to#ListenAddress ::#ListenAddress 0.0.0.0Protocol 2# HostKeys for protocol version 2HostKey /etc/ssh/ssh_host_rsa_keyHostKey /etc/ssh/ssh_host_dsa_keyHostKey /etc/ssh/ssh_host_ecdsa_key#Privilege Separation is turned on for securityUsePrivilegeSeparation yes!# Lifetime and size of ephemeral version 1 server keyKeyRegenerationInterval 3600ServerKeyBits 768# LoggingSyslogFacility AUTHLogLevel INFO# Authentication:LoginGraceTime 120

Page 27: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

FIRST5: SSH - EXAMPLE"## README.md"## tasks&   "## main.yml&   %## ssh_config.yml"## templates&   %## ssh_config.j2%## vars %## main.yml

# {{ ansible_managed }}# See the sshd_config(5) manpage for details!# What ports, IPs and protocols we listen forPort {{ ssh_port }}# Use these options to restrict which interfaces/protocols sshd will bind to#ListenAddress ::#ListenAddress 0.0.0.0Protocol 2# HostKeys for protocol version 2HostKey /etc/ssh/ssh_host_rsa_keyHostKey /etc/ssh/ssh_host_dsa_keyHostKey /etc/ssh/ssh_host_ecdsa_key#Privilege Separation is turned on for securityUsePrivilegeSeparation yes!# Lifetime and size of ephemeral version 1 server keyKeyRegenerationInterval 3600ServerKeyBits {{ ssh_server_key_bits }}# LoggingSyslogFacility AUTHLogLevel INFO# Authentication:LoginGraceTime {{ ssh_login_grace_time }}

Page 28: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

FIRST5: SSH"## README.md"## tasks&   "## main.yml&   %## ssh_config.yml"## templates&   %## ssh_config.j2%## vars %## main.yml# SSH Settings # optionally change port ssh_port: 22034 # reduce login grace time from 120 (2 minutes) ssh_login_grace_time: 20 # increase the server key bit encryption default=768 ssh_server_key_bits: 4096 # control the parallelism ssh_max_startups: 3:50:10 # control forwarding ssh_allow_tcp_forwarding: “no” ssh_allow_x11_forwarding: “no”

Page 29: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

FIRST5: SSH"## README.md"## tasks&   "## main.yml&   %## ssh_config.yml"## templates&   %## ssh_config.j2%## vars %## main.yml

--- - name: SSH Config | add ssh config file template: > src=ssh_config.j2 dest=/etc/ssh/sshd_config backup=yes notify: restart ssh

Page 30: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: FIRST 5---- hosts: all gather_facts: true sudo: true! pre_tasks: - name: Pretask | Update apt cache apt: update_cache=yes cache_valid_time=3600! - name: Pretask | Run apt-get upgrade apt: upgrade=dist roles: - { role: base , tags: ["base"] } - { role: ntp , tags: ["ntp"] } - { role: user, tags: ["user"] } - { role: ssh , tags: ["ssh"] } - { role: fail2ban, tags: ["fail2ban"] } - { role: logwatch , tags: ["logwatch"] } - { role: exim , tags: ["exim"] } - { role: geerlingguy.firewall, tags: ["iptables"] } handlers: - include: common/handlers/main.yml

Don’t reinvent the wheelUse Galaxy Roleswhere relevant

Page 31: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE BASICS: PROVISION

--- - hosts: all roles: - geerlingguy.mysql - geerlingguy.apache - geerlingguy.php

A LAMP SERVER IN SIX LINES OF YAMLJeff Geerling - Ansible for Devops

Page 32: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: SSL POODLE

- name: Apache security | SSL Poodle update lineinfile: dest=/etc/apache2/mods-available/ssl.conf regexp="{{ item.regexp }}" line="{{ item.line }}" backup=yes with_items: - { regexp: "^# enable only secure protocols:", line: "# enable only secure protocols: TLSv1, but not SSLv2 & SSLv3" } - { regexp: "^SSLProtocol", line: "SSLProtocol all -SSLv2 -SSLv3" } notify: restart apache tags: - poodle

Page 33: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: SSL POODLE

- name: Apache security | SSL Poodle update template: src=ssl-poodle.conf.j2 dest=/etc/apache2/conf.d/ssl.conf notify: restart apache tags: - poodle

# {{ ansible_managed }}<IfModule mod_ssl.c>!# enable only secure protocols: TLSv1, but not SSLv2 & SSLv3SSLProtocol all -SSLv2 -SSLv3!</IfModule>

SSL-POODLE.CONF.J2

Page 34: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY

Ansible role quickly address security issues such as SA-CORE-2014-005

Inventory of Drupal sites

Task to apply patch

Test for vulnerability

Re-use for future patches

Page 35: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY"## common&   "## handlers&   &   %## main.yml&   %## vars&   "## debian.yml&   %## os_default.yml"## group_vars&   "## all"## host_vars&   %## local&   %## example.server.net"## hosts"## log&   %## ansible.log"## patch.yml"## roles   %## SA-CORE-2014-005   "## README.md   "## files   &   "## SA-CORE-2014-005-D7.patch   &   %## dbtng.patch   "## meta   &   %## main.yml   %## tasks   %## main.yml

SA-CORE-2014-005

Page 36: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY

%## SA-CORE-2014-005 "## README.md "## files &   "## SA-CORE-2014-005-D7.patch &   %## dbtng.patch "## meta &   %## main.yml %## tasks %## main.yml

SA-CORE-2014-005

Page 37: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY---!ansible_ssh_host: 123.123.123.123!webroot: "/var/www"!drupal7_sites: - { drupal_docroot: "{{ webroot }}/example.d7.site/live/htdocs”, vhost_name: "example.d7.site.live" } - { drupal_docroot: "{{ webroot }}/example.d7.site/dev/htdocs", vhost_name: “example.d7.site.dev" } - { drupal_docroot: "{{ webroot }}/example.d7.site/staging/htdocs", vhost_name: "example.d7.staging" } drupal6_sites: - { drupal_docroot: "{{ webroot }}example.d6.site", vhost_name: "example.d6.site" }

host_vars: example.server.net

Page 38: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY

---# tasks file for SA-CORE-2014-005-D7!- name: Drupal7 patch | get patch | SA-CORE-2014-005-D7. get_url: url: https://www.drupal.org/files/issues/SA-CORE-2014-005-D7.patch dest: /tmp/SA-CORE-2014-005-D7.patch!- name: Drupal7 patch | Apply the patch from the drupal docroot. shell: "patch -p1 < /tmp/SA-CORE-2014-005-D7.patch chdir={{ item.drupal_docroot }}" with_items: - "{{ drupal7_sites }}"!- name: Drupal7 patch | Clear Drupal caches. command: "drush cc all chdir={{ item.drupal_docroot }}" with_items: - "{{ drupal7_sites }}"

Role: SA-CORE-2014-005-D7 - main.yml

see blog post: http://www.midwesternmac.com/blogs/jeff-geerling/fixing-drupal-fast-using

Page 39: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY

!- name: Drupal6 patch | get patch | SA-CORE-2014-005-D7. copy: src=dbtng.patch dest=/tmp/SACORE2014005D6-dbtng.patch owner=root group=root mode=0644 - name: Drupal6 patch | Apply the patch from the drupal docroot. shell: "patch -p1 < /tmp/SACORE2014005D6-dbtng.patch chdir={{ item.drupal_docroot }}" with_items: - "{{ drupal6_sites }}" tags: D6

Role: SA-CORE-2014-005-D7 - main.yml - (cont..)

Page 40: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY

Subscribe to the security bulletins

Follow key Drupal people on twitter

Harden your Drupal installations

Use version control

Leave Wednesday nights free

Page 41: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

Don’t use .htaccess

Migrate all .htaccess to vhosts

Get a static IP

Use custom robots.txt

BASIC SECURITY: DRUPAL SECURITY

Page 42: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

CUSTOM ROBOTS.TXT

Won’t get overwritten by Drupal update

RewriteCond %{REQUEST_URI} ^/robots\.txt$ [NC] RewriteRule robots.txt$ myrobots.txt [L]

Page 43: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

DRUPAL & VHOSTS

Disallow all txt other than robots.txt

Disallow all php other than index.php

Don’t use .htaccess

Migrate all .htaccess to vhosts

Get a static IP

Use custom robots.txt

Page 44: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

NO PHP FILES OTHER THAN INDEX.PHP

<FilesMatch "([^index].php|[^myrobots|robots].*\.txt)$"> AuthName "Development" AuthUserFile /etc/apache2/.htpasswds/passwd AuthType basic Require valid-user Order deny,allow Deny from all Allow from 123.123.123.123 Allow from 127.0.0.1 Satisfy Any</FilesMatch>

Page 45: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

DRUPAL & VHOSTS

Restrict file permissions (640 / 440)

Don’t use .htaccess

Migrate all .htaccess to vhosts

Get a static IP

Use custom robots.txt

Disallow all txt other than robots.txt

Disallow all php other than index.php

Page 46: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

TEST BEFORE RESTART

$ apachectl configtestSyntax error on line 46 of example.local.conf:

RewriteRule: bad flag delimiters

$ apachectl configtest $ apachectl graceful

RewriteRule ^ index.php [L, NC]

RewriteRule ^ index.php [L,NC]

46

# If you are on RHEL/CentOS:$ apachectl -t$ /etc/init.d/httpd restart

Page 47: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY

Review your logs

Subscribe to the security bulletins

Follow key Drupal people on twitter

Harden your Drupal installations

Use version control

Leave Wednesday nights free

Page 48: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

KEEP YOUR LOGS SLIM

## flag robots.txt requests - allow these to test robot behaviour SetEnvIf Request_URI "^/robots\.txt$" robots-request=log ## flag favicon requests SetEnvIf Request_URI "^/favicon\.ico$" favicon-request=nolog ## set do_not_log if any of the above flags are set SetEnvIf robots-request nolog do_not_log SetEnvIf favicon-request nolog do_not_log ## only log if do_not_log is not set CustomLog /var/www/log/mysite-access.log vcommon env=!do_not_log

Page 49: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

KEEP YOUR LOGS SLIM## flag robots.txt requests - allow these to test robot behaviour SetEnvIf Request_URI "^/robots\.txt$" robots-request=log ## flag favicon requests SetEnvIf Request_URI "^/favicon\.ico$" favicon-request=nolog ## flag image, Css and JS requests and other static assets SetEnvIf Request_URI “.(eot|js|css|woff|gif|png|jp(e)g))$” is_static_asset=nolog ## flag cron calls SetEnvIf Request_URI "^(.*)cron.php$" cron-request=nolog ## flag monitor calls BrowserMatchNoCase NewRelicPinger monitor-request=nolog ## set do_not_log if any of the above flags are set SetEnvIf robots-request nolog do_not_log SetEnvIf favicon-request nolog do_not_log SetEnvIf image-request nolog do_not_log SetEnvIf is_static_asset nolog do_not_log SetEnvIf monitor-request nolog do_not_log ## only log if do_not_log is not set CustomLog /var/www/log/mysite-access.log vcommon env=!do_not_log

Page 50: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: GENERAL SECURITY

Mod_securityDrupal specific rules and exclusionsmanage exclusions with Ansible

Know your application ‘surface’

Page 51: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

## {{ ansible_managed }}!SecRule RESPONSE_STATUS "@streq 408" "phase:5,t:none,nolog,pass, setvar:ip.slow_dos_counter=+1, expirevar:ip.slow_dos_counter=60, id:'990002'"!SecRule IP:SLOW_DOS_COUNTER "@gt 5" "phase:1,t:none,log,drop, msg:'Client Connection Dropped due to high number of slow DoS alerts', id:'990003'"!SecRule ARGS "ansibletesttoseeifmodsisworking" "phase:1,log,deny,status:503,msg:'Test Rule',id:'990004'"!# Rules to allow good bots with no request header - Don’t do this!!# SecRule REQUEST_HEADERS:User-Agent "Google|Bing|Yandex" "phase:1,t:none,allow,nolog,ctl:ruleRemoveById=960015"# Do this (use Ansible to manage IP list / User-Agents are spoofed)SecRule REMOTE_ADDR "^66.249.64.165" phase:1,nolog,allow,ctl:ruleEngine=off,id:960015!<LocationMatch "/admin/structure/[pages|views|types]"> SecRuleRemoveById 981173 SecRuleRemoveById 960024 SecRuleRemoveById 981231</LocationMatch>

BASIC SECURITY: GENERAL SECURITY./templates/modsecurity_crs_48_local_exceptions.conf.j2

Page 52: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: GENERAL SECURITY

Mod_securityDrupal specific rule and exclusionsmanage exclusions with Ansible

Fail2BanDrupal specific actions

IPTables - Whitelists

Remove all unused services

Consider log analysis servicese.g. loggly, paper trail, sumo logic

Know your application ‘surface’

Page 53: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE & DRUPAL

Put all sites in maintenance mode(Note: better to use maintenance site and re-point traffic to that so you can still work on your site on your ip)

Pull latest changes

Use in harmony with Drush

Clear caches and other Drush actionssee https://github.com/jenitehan/drupal_update_check

Extend Drush / Drupal to output JSON

Automate common tasks

Page 54: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

BASIC SECURITY: DRUPAL SECURITY

Consider a platform provider

Subscribe to the security bulletins

Follow key Drupal people on twitter

Harden your Drupal installations

Use version control

Review your logs

Use security best practices

Page 55: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE & DRUPAL: EXAMPLE 2Use Case: Commerce site

Product Image updates

Replace the image(s)

Clear the Image Cache/ styles

Page 56: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ansible_ssh_host: 123.123.123.123ansible_ssh_user: ansibledrupal_sites: - “/var/www/mysite/live/htdocs” - “/var/www/mysite/staging/htdocs" - "/var/www/mysite/dev/htdocs"

ANSIBLE & DRUPAL: EXAMPLE 2./host_vars/server.example.com

./main.yml---- hosts: all gather_facts: false sudo: true! roles: - { role: updateimages , tags: ["updateimages"] }! handlers: - include: common/handlers/main.yml

./hosts[example]server.example.com

Page 57: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

---# vars file for basefiles_src_path: “/path/to/local/updated/images”files_dest_path: “/sites/default/files”files_to_update: - “fa9001.jpg" - “fa9002.jpg" image_cache_folders: - “styles/thumbnail/public/product_images" - "styles/product_gallery/public/product_images" - "styles/medium_tall/public/product_images" - "styles/product_full/public/product_images"

ANSIBLE & DRUPAL: EXAMPLE 1./roles/updateimages/vars/main

---- name: clear drupal cache command: "drush cc all chdir={{ item }}" with_items: - "{{ drupal_sites }}"

./handlers/main.yml

Page 58: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

- name: Image Update | Products copy: src={{ files_src_path }}/{{ item[1] }} dest={{ item[0] }}/{{ files_dest_path }}/product_images/{{ item[1] }} owner=www-data group=www-data mode:0644 with_nested: - drupal_sites - files_to_update tags: images notify: clear drupal cache!- name: Image Update | Update Cache file: > path={{ item[0] }}/{{ files_dest_path }}/{{ item[1] }}/{{ item[2] }} state=absent with_nested: - drupal_sites - image_cache_folders - files_to_update tags: images notify: clear drupal cache

ANSIBLE & DRUPAL: EXAMPLE 2./roles/updateimages/tasks/main.yml

Page 59: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

RUN UPDATE

TASK: [updateimages | Image Update | Products] ****************

ok: [server.example.com] => (item=['/var/www/mysite/live/htdocs', 'fa9001.jpg']) => {"changed": false, "checksum": "9b36d8209ee8287385b1ce6af48bb033ade468a3", "dest": "/var/www/mysite/live/htdocs/sites/default/files/product_images/fa9001.jpg", "gid": 33, "group": "www-data", "item": "fa9001.jpg", "mode": "0644", "owner": "www-data", "path": “/var/www/mysite/live/htdocs/sites/default/files/product_images/fa9001.jpg", "size": 193018, "state": "file", "uid": 33}

changed: [server.example.com] => (item=['/var/www/mysite/staging/htdocs', 'fa9001.jpg']) => {"changed": true, "checksum": "e2d70c097b6fb5900045774e710cfbc9dcadde1a", "dest": "/var/www/mysite/staging/htdocs/sites/default/files/product_images/fa9001.jpg", "gid": 33, "group": "www-data", "item": "fa9001.jpg", "md5sum": "10df9698fd4f743fd199372255b15f33", "mode": "0644", "owner": "www-data", "size": 63598, "src": "/home/georgeb/.ansible/tmp/ansible-tmp-1420799222.5-262099501965035/source", "state": "file", "uid": 33}

changed: [server.example.com] => (item=['/var/www/mysite/dev/htdocs', 'fa9001.jpg']) => {"changed": true, "checksum": "e2d70c097b6fb5900045774e710cfbc9dcadde1a", "dest": "/var/www/mysite/dev/htdocs/sites/default/files/product_images/fa9001.jpg", "gid": 33, "group": "www-data", "item": "fa9001.jpg", "md5sum": "10df9698fd4f743fd199372255b15f33", "mode": "0644", "owner": "www-data", "size": 63598, "src": "/home/georgeb/.ansible/tmp/ansible-tmp-1420799222.5-262099501965035/source", "state": "file", "uid": 33}

$ ansible-playbook main.yml -l server.example.com -u ansible -K -v --tags "updateimages"

Page 60: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

RUN UPDATE IMAGES PLAYTASK: [updateimages | Image Update | Update Cache] **************************

ok: [server.example.com] => (item=['thumbnail/public/product_images', 'fa9001.jpg']) => {"changed": false, "item": ["thumbnail/public/product_images", "fa9001.jpg"], "path": "/var/www/mysite/live/htdocs/sites/default/files/styles/thumbnail/public/product_images/fa9001.jpg", "state": “absent”}

changed: [server.example.com] => (item=['product_gallery/public/product_images', 'fa9001.jpg']) => {"changed": true, "item": ["product_gallery/public/product_images", "fa9001.jpg"], "path": "/var/www/mysite/live/htdocs/sites/default/files/styles/product_gallery/public/product_images/fa9001.jpg", "state": "absent"}

changed: [server.example.com] => (item=['medium_tall/public/product_images', 'fa9001.jpg']) => {"changed": true, "item": ["medium_tall/public/product_images", "fa9001.jpg"], "path": "/var/www/mysite/live/htdocs/sites/default/files/styles/medium_tall/public/product_images/fa9001.jpg", "state": "absent"}

changed: [server.example.com] => (item=['product_full/public/product_images', 'fa9001.jpg']) => {"changed": true, "item": ["product_full/public/product_images", "fa9001.jpg"], "path": "/var/www/mysite/live/htdocs/sites/default/files/styles/product_full/public/product_images/fa9001.jpg", "state": "absent"}

PLAY RECAP ********************************************************************

server.example.com : ok=2 changed=2 unreachable=0 failed=0

Page 61: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

ANSIBLE TOOLS

Automate playbook runs

Collaborate

Log

Permissions

Scheduled runs

Push button deployment

Free for < 10 nodes

Page 62: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

SOME USEFUL TOOLS

Unicode Code Converter: http://rishida.net/tools/conversion/

PHP Decoder / Hex Decoder: http://ddecode.com/phpdecoder/

Permissions Calculator: http://permissions-calculator.org/

RegEx:https://regex101.com/#pcre

Network Tools: CIDR masks etchttp://pingtool.org/

Page 63: Drupal Camp Brighton 2015: Ansible Drupal Medicine show

blue-bag

CONCLUSION / QUESTIONS

For all local development

use VLAD

http://git.io/DCB-Vlad

For Ansible get the books

https://leanpub.com/ansible-for-devops

http://www.ansible.com/ansible-book