From 00d6d904dc26592553ba93710c205603757e3faf Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Wed, 3 Jun 2015 21:13:10 +0200 Subject: Configure Bacula File Daemon / Storage Daemon / Director. Using client-side data signing/encryption and wrapping inter-host communication into stunnel. --- .../files/lib/systemd/system/bacula-fd.service | 12 ++ roles/common/handlers/main.yml | 9 ++ roles/common/tasks/bacula.yml | 150 +++++++++++++++++++++ roles/common/tasks/main.yml | 1 + .../common/templates/etc/bacula/bacula-fd.conf.j2 | 41 ++++++ roles/common/templates/etc/iptables/services.j2 | 10 ++ .../common/templates/etc/stunnel/bacula-fd.conf.j2 | 62 +++++++++ 7 files changed, 285 insertions(+) create mode 100644 roles/common/files/lib/systemd/system/bacula-fd.service create mode 100644 roles/common/tasks/bacula.yml create mode 100644 roles/common/templates/etc/bacula/bacula-fd.conf.j2 create mode 100644 roles/common/templates/etc/stunnel/bacula-fd.conf.j2 (limited to 'roles/common') diff --git a/roles/common/files/lib/systemd/system/bacula-fd.service b/roles/common/files/lib/systemd/system/bacula-fd.service new file mode 100644 index 0000000..6e2bbd4 --- /dev/null +++ b/roles/common/files/lib/systemd/system/bacula-fd.service @@ -0,0 +1,12 @@ +[Unit] +Description=Bacula File Daemon service +After=network.target + +[Service] +Type=forking +PIDFile=/var/run/bacula/bacula-fd.9112.pid +StandardOutput=syslog +ExecStart=/usr/sbin/bacula-fd -c /etc/bacula/bacula-fd.conf + +[Install] +WantedBy=multi-user.target diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml index ddfe86b..b7ecaab 100644 --- a/roles/common/handlers/main.yml +++ b/roles/common/handlers/main.yml @@ -2,6 +2,9 @@ # corresponding state=restarted handler. (Register the task notifying # the handler, and add a conditional.) --- +- name: systemctl daemon-reload + command: /bin/systemctl daemon-reload + - name: Refresh hostname service: name=hostname.sh state=restarted @@ -35,5 +38,11 @@ - name: Reload Postfix service: name=postfix state=reloaded +- name: Restart stunnel + service: name=stunnel4 pattern=/usr/bin/stunnel4 state=restarted + +- name: Restart bacula-fd + service: name=bacula-fd state=restarted + - name: Update certificate command: update-ca-certificates diff --git a/roles/common/tasks/bacula.yml b/roles/common/tasks/bacula.yml new file mode 100644 index 0000000..248d47d --- /dev/null +++ b/roles/common/tasks/bacula.yml @@ -0,0 +1,150 @@ +- name: Install stunnel + apt: pkg=stunnel4 + +- name: Auto-enable stunnel + lineinfile: dest=/etc/default/stunnel4 + regexp='^(\s*#)?\s*ENABLED=' + line='ENABLED=1' + owner=root group=root + mode=0644 + +- name: Create /etc/stunnel/certs + file: path=/etc/stunnel/certs + state=directory + owner=root group=root + mode=0755 + +- name: Generate a private key and a X.509 certificate for Bacula FD + command: genkeypair.sh x509 + --pubkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem + --privkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.key + --ou=BaculaFD --cn={{ inventory_hostname }} --dns={{ inventory_hostname }} + -t rsa -b 4096 -h sha512 + register: r1 + changed_when: r1.rc == 0 + failed_when: r1.rc > 1 + notify: + - Restart stunnel + tags: + - genkey + +- name: Fetch Bacula FD X.509 certificate + # Ensure we don't fetch private data + sudo: False + fetch: src=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem + dest=certs/bacula/ + fail_on_missing=yes + flat=yes + tags: + - genkey + +- name: Copy Bacula Dir X.509 certificates + assemble: src=certs/bacula regexp="-dir\.pem$" remote_src=no + dest=/etc/stunnel/certs/bacula-dirs.pem + owner=root group=root + mode=0644 + register: r2 + when: "'bacula-dir' not in group_names" + notify: + - Restart stunnel + +- name: Copy Bacula SD X.509 certificates + copy: src=certs/bacula/{{ hostvars[item].inventory_hostname_short }}-sd.pem + dest=/etc/stunnel/certs/ + owner=root group=root + mode=0644 + register: r3 + with_items: groups['bacula-sd'] | difference([inventory_hostname]) + notify: + - Restart stunnel + +- name: Configure stunnel + template: src=etc/stunnel/bacula-fd.conf.j2 + dest=/etc/stunnel/bacula-fd.conf + owner=root group=root + mode=0644 + register: r4 + when: "'bacula-dir' not in group_names or 'bacula-sd' not in group_names" + notify: + - Restart stunnel + +- name: Start stunnel + service: name=stunnel4 pattern=/usr/bin/stunnel4 state=started + when: not (r1.changed or r2.changed or r3.changed or r4.changed) + +- meta: flush_handlers + + + +- name: Install bacula-fd + apt: pkg=bacula-fd + +- name: Create /var/lib/bacula/tmp + file: path=/var/lib/bacula/tmp + state=directory + owner=root group=root + mode=0700 + +- name: Delete /etc/bacula/common_default_passwords + file: path=/etc/bacula/common_default_passwords state=absent + +# Create with: +# echo $director-dir $(pwgen -sn 64 1) | sudo tee -a /etc/bacula/passwords-fd +- name: Ensure /etc/bacula/passwords-fd exists + file: path=/etc/bacula/passwords-fd + state=file + owner=root group=root + mode=0600 + +- name: Configure bacula + template: src=etc/bacula/bacula-fd.conf.j2 + dest=/etc/bacula/bacula-fd.conf + owner=root group=root + mode=0644 + notify: + - Restart bacula-fd + +- name: Create /etc/bacula/ssl + file: path=/etc/bacula/ssl + state=directory + owner=root group=root + mode=0755 + +- name: Generate a keypair for data encryption + command: genkeypair.sh x509 + --pubkey=/etc/bacula/ssl/{{ inventory_hostname_short }}.pem + --privkey=/etc/bacula/ssl/{{ inventory_hostname_short }}.pem + --ou=BaculaFD --cn={{ inventory_hostname }} --dns={{ inventory_hostname }} + -t rsa -b 4096 -h sha512 + register: r + changed_when: r.rc == 0 + failed_when: r.rc > 1 + notify: + - Restart bacula-fd + tags: + - genkey + +- name: Copy the master public key for data encryption + copy: src=certs/bacula/data-master.pem + dest=/etc/bacula/ssl/master.pem + owner=root group=root + mode=0644 + tags: + - genkey + +- name: Copy bacula-fd.service + copy: src=lib/systemd/system/bacula-fd.service + dest=/lib/systemd/system/bacula-fd.service + owner=root group=root + mode=0644 + notify: + - systemctl daemon-reload + - Restart bacula-fd + +- meta: flush_handlers + +- name: Enable bacula-fd + service: name=bacula-fd enabled=yes + +- name: Start bacula-fd + service: name=bacula-fd state=started diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml index 8f28b93..477bd34 100644 --- a/roles/common/tasks/main.yml +++ b/roles/common/tasks/main.yml @@ -30,6 +30,7 @@ - include: logging.yml tags=logging - include: ntp.yml tags=ntp - include: mail.yml tags=mail,postfix +- include: bacula.yml tags=bacula-fd,bacula - name: Install common packages apt: pkg={{ item }} diff --git a/roles/common/templates/etc/bacula/bacula-fd.conf.j2 b/roles/common/templates/etc/bacula/bacula-fd.conf.j2 new file mode 100644 index 0000000..a47bb90 --- /dev/null +++ b/roles/common/templates/etc/bacula/bacula-fd.conf.j2 @@ -0,0 +1,41 @@ +# +# Default Bacula File Daemon Configuration file +# +# For Bacula release 5.2.6 (21 February 2012) -- debian jessie/sid + +# +# List Directors who are permitted to contact this File daemon +# +{% for dir in groups['bacula-dir'] | sort %} +Director { + Name = {{ hostvars[dir].inventory_hostname_short }}-dir + @|"sed -n '/^{{ hostvars[dir].inventory_hostname_short }}-dir\\s/ {s//Password = /p; q}' /etc/bacula/passwords-fd" +} + +# Send all messages except skipped files back to Director +Messages { + Name = Standard + director = {{ hostvars[dir].inventory_hostname_short }}-dir = all, !skipped, !restored +} +{% endfor %} + +# +# "Global" File daemon configuration specifications +# +FileDaemon { # define myself + Name = {{ inventory_hostname_short }}-fd + Working Directory = /var/lib/bacula + Pid Directory = /var/run/bacula + Maximum Concurrent Jobs = 20 + FDAddress = 127.0.0.1 + FDPort = 9112 + FDSourceAddress = 127.0.0.1 +{% if 'bacula-dir' not in group_names or 'bacula-sd' not in group_names %} + Heartbeat Interval = 60s +{% endif %} + + PKI Signatures = Yes # Enable Data Signing + PKI Encryption = Yes # Enable Data Encryption + PKI Keypair = /etc/bacula/ssl/{{ inventory_hostname_short }}.pem # Public and Private Keys + PKI Master Key = /etc/bacula/ssl/master.pem # ONLY the Public Key +} diff --git a/roles/common/templates/etc/iptables/services.j2 b/roles/common/templates/etc/iptables/services.j2 index 187e588..a0bb714 100644 --- a/roles/common/templates/etc/iptables/services.j2 +++ b/roles/common/templates/etc/iptables/services.j2 @@ -59,6 +59,16 @@ in tcp 80,443 # HTTP/HTTPS out tcp 993 # IMAP out tcp 4190 # MANAGESIEVE {% endif %} +{% if 'bacula-dir' in group_names and groups.all | difference(groups['bacula-dir']) %} +out tcp 9102 # BACULA-FD +{% elif groups['bacula-dir'] | difference([inventory_hostname]) %} +in tcp 9102 # BACULA-FD +{% endif %} +{% if 'bacula-sd' in group_names and groups.all | difference(groups['bacula-sd']) %} +in tcp 9103 # BACULA-SD +{% elif groups['bacula-sd'] | difference([inventory_hostname]) %} +out tcp 9103 # BACULA-SD +{% endif %} {% if 'LDAP-provider' in group_names %} out tcp 11371 # HKP diff --git a/roles/common/templates/etc/stunnel/bacula-fd.conf.j2 b/roles/common/templates/etc/stunnel/bacula-fd.conf.j2 new file mode 100644 index 0000000..74364c9 --- /dev/null +++ b/roles/common/templates/etc/stunnel/bacula-fd.conf.j2 @@ -0,0 +1,62 @@ +; ************************************************************************** +; * Global options * +; ************************************************************************** + +; setuid()/setgid() to the specified user/group in daemon mode +setuid = stunnel4 +setgid = stunnel4 + +; PID is created inside the chroot jail +pid = /var/run/stunnel4/bacula-fd.pid + +; Only log messages at severity warning (4) and higher +debug = 4 + +; ************************************************************************** +; * Service defaults may also be specified in individual service sections * +; ************************************************************************** + +; Certificate/key is needed in server mode and optional in client mode +cert = /etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem +key = /etc/stunnel/certs/{{ inventory_hostname_short }}-fd.key + +; Some performance tunings +socket = l:TCP_NODELAY=1 +socket = r:TCP_NODELAY=1 + +; Prevent MITM attacks +verify = 4 + +; Disable support for insecure protocols +options = NO_SSLv2 +options = NO_SSLv3 +options = NO_TLSv1 +options = NO_TLSv1.1 + +; These options provide additional security at some performance degradation +options = SINGLE_ECDH_USE +options = SINGLE_DH_USE + +; Select permitted SSL ciphers +ciphers = EECDH+AES:EDH+AES:!MEDIUM:!LOW:!EXP:!aNULL:!eNULL:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1 + +; ************************************************************************** +; * Service definitions (remove all services for inetd mode) * +; ************************************************************************** + +[{{ inventory_hostname_short }}-fd] +client = no +accept = 9102 +connect = 9112 +CAfile = /etc/stunnel/certs/bacula-dirs.pem + +{% if 'bacula-sd' not in group_names %} +[{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd] +client = yes +accept = 127.0.0.1:9113 +connect = {{ groups['bacula-sd'][0] }}:9103 +delay = yes +CAfile = /etc/stunnel/certs/{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd.pem +{% endif %} + +; vim:ft=dosini -- cgit v1.2.3