stafwag Blog

staf wagemakers blog

Bacula on FreeBSD (Part 2 Bacula Catalog Over SSL )

"PostgreSSL"

In my previous post, I setup on my PostgresSQL FreeBSD jail, In this post we continue with the bacaula server.

In this post we will continue with the database connection (Catalog) we’ll go the extra mile 1,609344 km and encrypt the catalog connection with ssl. Why? We encrypt.. because we can!

Bacula Components

  • Bacula Director
    The Bacula Director is daemon that runs in the backgroud that control all backup operations.

  • Bacula Console
    The Bacula console is an administrator program that allows an system administrator to control the Bacula director.

  • Bacula File
    The Bacula File is a backup client install on the backup client.

  • Bacula Storage
    The backup media.

  • Catalog
    The Catalog is the index of the backups. Bacula supports three types of index databases mySQL ( mariaDB), PostgreSQL and SQLite

  • Bacula monitor
    A Bacula monitor service is a program that allows the system administrator to cerify the status of the bacula Directors, Bacula File Daemons and Bacula Storage Daemons.

Bacula Server

Jail

Create the Bacula Server Jail

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@rataplan:~ # ezjail-admin create stafbacula "em0|192.168.1.52"
Warning: Some services already seem to be listening on all IP, (including 192.168.1.52)
  This may cause some confusion, here they are:
root     ntpd       754   20 udp6   *:123                 *:*
root     ntpd       754   21 udp4   *:123                 *:*
root     rpc.statd  717   4  udp6   *:846                 *:*
root     rpc.statd  717   5  tcp6   *:846                 *:*
root     rpc.statd  717   6  udp4   *:846                 *:*
root     rpc.statd  717   7  tcp4   *:846                 *:*
root     nfsd       713   5  tcp4   *:2049                *:*
root     nfsd       713   6  tcp6   *:2049                *:*
root     mountd     707   5  udp6   *:823                 *:*
root     mountd     707   6  tcp6   *:823                 *:*
root     mountd     707   7  udp4   *:823                 *:*
root     mountd     707   8  tcp4   *:823                 *:*
root     rpcbind    676   6  udp6   *:111                 *:*
root     rpcbind    676   7  udp6   *:779                 *:*
root     rpcbind    676   8  tcp6   *:111                 *:*
root     rpcbind    676   9  udp4   *:111                 *:*
root     rpcbind    676   10 udp4   *:768                 *:*
root     rpcbind    676   11 tcp4   *:111                 *:*
root     syslogd    656   6  udp6   *:514                 *:*
root     syslogd    656   7  udp4   *:514                 *:*
root@rataplan:~ # 

Start the jail

1
2
3
4
root@rataplan:~ # ezjail-admin start stafbacula
Starting jails: stafbacula.
/etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables  is obsolete.  Please consider migrating to /etc/jail.conf.
root@rataplan:~ # 

Open the console

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@rataplan:~ # ezjail-admin console stafbacula
FreeBSD 11.1-RELEASE-p1 (GENERIC) #0: Wed Sep  9 11:55:48 UTC 2017

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

Edit /etc/motd to change this login announcement.
root@stafbacula:~ # 

Bacula installation

Install pkg

Set up dns

1
root@stafbacula:~ # vi /etc/resolv.conf
1
nameserver 192.168.1.1

Bootstrap pkg

1
2
3
4
5
6
7
8
9
10
11
12
root@stafbacula:~ # pkg
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y
Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:11:amd64/quarterly, please wait...
Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done
[stafbacula] Installing pkg-1.10.1...
[stafbacula] Extracting pkg-1.10.1: 100%
pkg: not enough arguments
Usage: pkg [-v] [-d] [-l] [-N] [-j <jail name or id>|-c <chroot path>|-r <rootdir>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] [-4|-6] <command> [<args>]

For more information on available commands and options see 'pkg help'.
root@stafbacula:~ # 

Install the bacula server package

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
root@stafbacula:~ # pkg install bacula-server
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
Updating database digests format: 100%
The following 8 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        bacula-server: 7.4.7_1
        bacula-client: 7.4.7_1
        readline: 7.0.3
        indexinfo: 0.2.6
        gettext-runtime: 0.19.8.1_1
        lzo2: 2.10_1
        postgresql95-client: 9.5.7_1
        perl5: 5.24.1_1

Number of packages to be installed: 8

The process will require 69 MiB more space.
17 MiB to be downloaded.

Proceed with this action? [y/N]: y
[stafbacula] [1/8] Fetching bacula-server-7.4.7_1.txz: 100%  678 KiB 694.6kB/s    00:01    
[stafbacula] [2/8] Fetching bacula-client-7.4.7_1.txz: 100%  286 KiB 292.8kB/s    00:01    
[stafbacula] [3/8] Fetching readline-7.0.3.txz: 100%  334 KiB 342.4kB/s    00:01    
[stafbacula] [4/8] Fetching indexinfo-0.2.6.txz: 100%    5 KiB   5.3kB/s    00:01    
[stafbacula] [5/8] Fetching gettext-runtime-0.19.8.1_1.txz: 100%  148 KiB 151.1kB/s    00:01    
[stafbacula] [6/8] Fetching lzo2-2.10_1.txz: 100%  113 KiB 115.4kB/s    00:01    
[stafbacula] [7/8] Fetching postgresql95-client-9.5.7_1.txz: 100%    2 MiB 772.9kB/s    00:03    
[stafbacula] [8/8] Fetching perl5-5.24.1_1.txz: 100%   13 MiB 874.0kB/s    00:16    
Checking integrity... done (0 conflicting)
[stafbacula] [1/8] Installing indexinfo-0.2.6...
[stafbacula] [1/8] Extracting indexinfo-0.2.6: 100%
[stafbacula] [2/8] Installing readline-7.0.3...
[stafbacula] [2/8] Extracting readline-7.0.3: 100%
[stafbacula] [3/8] Installing gettext-runtime-0.19.8.1_1...
[stafbacula] [3/8] Extracting gettext-runtime-0.19.8.1_1: 100%
[stafbacula] [4/8] Installing lzo2-2.10_1...
[stafbacula] [4/8] Extracting lzo2-2.10_1: 100%
[stafbacula] [5/8] Installing perl5-5.24.1_1...
[stafbacula] [5/8] Extracting perl5-5.24.1_1: 100%
[stafbacula] [6/8] Installing bacula-client-7.4.7_1...
===> Creating groups.
Creating group 'bacula' with gid '910'.
===> Creating users
Creating user 'bacula' with uid '910'.
[stafbacula] [6/8] Extracting bacula-client-7.4.7_1: 100%
[stafbacula] [7/8] Installing postgresql95-client-9.5.7_1...
[stafbacula] [7/8] Extracting postgresql95-client-9.5.7_1: 100%
[stafbacula] [8/8] Installing bacula-server-7.4.7_1...
===> Creating groups.
Using existing group 'bacula'.
===> Creating users
Using existing user 'bacula'.
[stafbacula] Extracting bacula-server-7.4.7_1: 100%
Message from perl5-5.24.1_1:
The /usr/bin/perl symlink has been removed starting with Perl 5.20.
For shebangs, you should either use:

#!/usr/local/bin/perl

or

#!/usr/bin/env perl

The first one will only work if you have a /usr/local/bin/perl,
the second will work as long as perl is in PATH.
Message from bacula-client-7.4.7_1:
################################################################################

NOTE:
Sample files are installed in /usr/local/etc/bacula:

  bconsole.conf.sample, bacula-fd.conf.sample

################################################################################
Message from postgresql95-client-9.5.7_1:
The PostgreSQL port has a collection of "side orders":

postgresql-docs
  For all of the html documentation

p5-Pg
  A perl5 API for client access to PostgreSQL databases.

postgresql-tcltk
  If you want tcl/tk client support.

postgresql-jdbc
  For Java JDBC support.

postgresql-odbc
  For client access from unix applications using ODBC as access
  method. Not needed to access unix PostgreSQL servers from Win32
  using ODBC. See below.

ruby-postgres, py-PyGreSQL
  For client access to PostgreSQL databases using the ruby & python
  languages.

postgresql-plperl, postgresql-pltcl & postgresql-plruby
  For using perl5, tcl & ruby as procedural languages.

postgresql-contrib
  Lots of contributed utilities, postgresql functions and
  datatypes. There you find pg_standby, pgcrypto and many other cool
  things.

etc...
Message from bacula-server-7.4.7_1:
###############################################################################

bacula server was installed

An auto-changer manipulation script based on FreeBSDs
chio command is included and installed at

  /usr/local/sbin/chio-bacula

Please have a look at it if you want to use an
autochanger. You have to configure the usage in

  /usr/local/etc/bacula/bacula-dir.conf

Take care of correct permissions for changer and
tape device (e.g. /dev/ch0 and /dev/n[r]sa0) i.e.
they must be accessible by user bacula.

Due to lack of some features in the FreeBSD tape driver
implementation you MUST add some OS dependent options to
the bacula-sd.conf file:

  Hardware End of Medium = no;
  Backward Space Record  = no;
  Backward Space File    = no;

With 2 filemarks at EOT (see man mt):
  Fast Forward Space File = no;
  BSF at EOM = yes;
  TWO EOF    = yes;

With 1 filemarks at EOT (see man mt):
  Fast Forward Space File = yes;
  BSF at EOM = no;
  TWO EOF   = no;

NOTE: YOU CAN SWITCH EOT model ONLY when starting
      from scratch with EMPTY tapes.

It is also important that all the scripts accessed
by RunBeforeJob and RunAfterJob will be executed by
the user bacula.  Check your permissions.

For USB support read the bacula manual. It could be necessary
to configure/compile a new kernel.

Look at /usr/local/share/bacula/update_bacula_tables for
database update procedure. Details can be found in the
ReleaseNotes

If you are using sqlite you need to run the make_sqlite_tables script as
the bacula user. Do this using 'sudo su -m bacula'.

################################################################################
root@stafbacula:~ # 

Initialize the bacula catalog

We’ll have a postgreSQL server running in a FreeBSD jail as our catalog (see http://stafwag.github.io/blog/blog/2017/08/06/bacula-on-freebsd:w_part1/ howto install PostgreSQL into a FreeBSD jail).

PostgreSQL setup

The setup below describes howto configure the PostgreSQL catalog with certificate and username/password authentication. This might be overkill the bacula server runs on the same physical host so no data is going out on the network. But I wanted to setup the database conneection as secure as possible and will reuse this setup for my other database connection. We’ll setup a “self signed” root ca for now, but I replace this with my own CA in further.

PostgreSQL authentication methods

PostgreSQL support a lot of authentication methods you’ll find a description of the supported of the support authentication methods below (without too much details):

  • Trust Authentication
    With trust authentication the postgreSQL trust the connection from the remote host, this is the default for localhost host connection and “socket” connections.
     
  • Password Authentication
    Authentication with login/password
     
  • GSSAPI Authentication
    Authentication with the Generic Security Services Application Program Interface
     
  • SSPI Authentication
    Authentication with the Security Support Provider Interface - SSPI is a proprietary variant of GSSAPI with extensions and very Windows-specific data types -
     
  • Kerberos Authentication
    Authentication using the Kerberos protocol
     
  • Ident Authentication
    Authentication using the ident protocol
     
  • Peer Authentication
    Authentication using the getpeereid() kernel function, only supported for local connection on BSD, MacOS and GNU/Linux.
     
  • LDAP Authentication
    LDAP authentication.
     
  • RADIUS Authentication
    Radius authentication.
     
  • Certificate Authentication
    Authentication with a PKI certificate.
     
  • PAM Authentication
    PAM based authentication
     

     
    I wanted to use password authentication over ssl with a client certificate. The bacula documents isn’t very clear on howto configure it. After a quick lot at the bacula source code it should be supported, so let’s give it a try…

Configure the PostgreSQL jail

Allow network connections

Logon the postgreSQL server jail move to the postgreSQL data directory and edit postgresql.conf to allow TCP/IP connections.

1
2
3
root@stafdb:/var/db/postgres/data96 # pwd
/var/db/postgres/data96
root@stafdb:/var/db/postgres/data96 # vim postgresql.conf
1
2
3
4
5
6
7
8
# - Connection Settings -

listen_addresses = '192.168.1.51'               # what IP address(es) to listen on;
# listen_addresses = 'localhost'                # what IP address(es) to listen on;
                                        # comma-separated list of addresses;
                                        # defaults to 'localhost'; use '*' for all
                                        # (change requires restart)
#port = 5432                            # (change requires restart)

SSL encryption

It’s always a good idea to encrypt your connections.

SSL Server setup
Umask

set the umask to prevent somebody can read you private key.

1
2
3
root@stafdb:/var/db/postgres/data96 # su - postgres
$ umask 077 
$ 
Create a private key

Create a private key without encrypting it.

1
2
3
4
5
6
openssl genrsa -out server.key 4096
Generating RSA private key, 4096 bit long modulus
........................................................................................................................................................................................................................++
......++
e is 65537 (0x10001)
$ 
Create a self-signed certificate
1
2
3
4
5
$ openssl req -new -key server.key -days 3650 -out server.crt -x509 -subj '/C=BE/ST=Flanders/L=Antwerp/O=stafnet/CN=stafdb'
$ ls -ltr                                                                                               total 23
-rw-------   1 postgres  postgres  3247 Sep  9 11:47 server.key
-rw-------   1 postgres  postgres  1964 Sep  9 11:52 server.crt
$ 
Root ca

We created a self signed certificate so the server certificate is our trusted ca root.

1
2
3
4
5
6
7
$ ln -s server.crt root.crt
$ ls -ltr
total 24
-rw-------   1 postgres  postgres  3247 Sep  9 11:47 server.key
-rw-------   1 postgres  postgres  1964 Sep  9 11:52 server.crt
lrwx------   1 postgres  postgres    10 Sep  9 11:53 root.crt -> server.crt
$ 
Enable ssl

Edit postgresql.conf and update the ssl setting

1
$ vi postgresql.conf

By default ssl_ca_file is not set but this directive is required so don’t forget to set it. We disable the 3DES ciphers they’re obsolete… We don’t speficy a crl for now.

1
2
3
4
5
6
7
8
9
10
11
#authentication_timeout = 1min          # 1s-600s
ssl = on                                # (change requires restart)
ssl_ciphers = 'HIGH:MEDIUM:!3DES:!aNULL' # allowed SSL ciphers
                                        # (change requires restart)
ssl_prefer_server_ciphers = on          # (change requires restart)
#ssl_ecdh_curve = 'prime256v1'          # (change requires restart)
ssl_cert_file = 'server.crt'            # (change requires restart)
ssl_key_file = 'server.key'             # (change requires restart)
ssl_ca_file = 'root.crt'                        # (change requires restart)
#ssl_crl_file = ''                      # (change requires restart)
#password_encryption = on
SSL Client setup
Become bacula

Logon to the bacula jail and become the bacula user. We use “su -m …” to logon to the locked daemon account, this will take over the root environment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
root@rataplan:~ # ezjail-admin console stafbacula
Last login: Wed Sep  9 09:33:16 on pts/0
FreeBSD 11.1-RELEASE-p1 (GENERIC) #0: Wed Sep  9 11:55:48 UTC 2017

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

Edit /etc/motd to change this login announcement.
You have new mail.
root@stafbacula:~ # su -m bacula -c "/bin/sh"
$ id
uid=910(bacula) gid=910(bacula) groups=910(bacula)
$ 
umask

Set the umask to prevent somebody can read you private key.

1
2
$ umask 077
$ 
move to the bacula home directory
1
2
3
$ cat /etc/passwd | grep bacula
bacula:*:910:910:Bacula Daemon:/var/db/bacula:/usr/sbin/nologin
$ cd /var/db/bacula
create the .postges directory
1
2
3
4
5
6
7
8
$ mkdir .postgres
$ ls -la
total 12
drwxrwx---   3 bacula  bacula   3 Sep  9 09:41 .
drwxr-xr-x  14 root    wheel   18 Sep  9 14:41 ..
drwx------   2 bacula  bacula   2 Sep  9 09:41 .postgres
$ cd .postgres/
$ 
Create a private key

We took over the root evironment therefor we need to set the RANDFILE variable to randfile in the bacula home directory.

1
2
3
4
$ pwd
/var/db/bacula/.postgres
$ export RANDFILE=/var/db/bacula/.rnd
$ 

Create the private key.

1
2
3
4
5
6
$ openssl genrsa -out `hostname`.key 4096
Generating RSA private key, 4096 bit long modulus
..........++
.......................................................++
e is 65537 (0x10001)
$ 
Create the client csr
1
2
$ openssl req -new -key stafbacula.key -out stafbacula.csr -subj '/C=BE/ST=Flanders/L=Antwerp/O=stafnet/CN=stafbacula'
$ 
Create the client certifocate

Logon to the postgreSQL jail as postgres and sign the client csr.

1
2
3
4
5
[postgres@stafdb ~/data96]$ openssl x509 -req -in stafbacula.csr -CAcreateserial -CA root.crt -CAkey server.key -out stafbacula.crt 
Signature ok
subject=/C=BE/ST=Flanders/L=Antwerp/O=stafnet/CN=stafbacula
Getting CA Private Key
[postgres@stafdb ~/data96]$ 
Copy the client certificate and the trusted root certificate to bacula jail
1
2
3
4
5
6
7
8
9
10
11
$ uname -a
FreeBSD stafbacula 11.1-RELEASE-p1 FreeBSD 11.1-RELEASE-p1 #0: Wed Sep  9 11:55:48 UTC 2017     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  amd64
$ pwd
/var/db/bacula/.postgres
$ ls -ltr
total 24
-rw-------  1 bacula  bacula  3243 Sep  9 09:47 stafbacula.key
-rw-------  1 bacula  bacula  1679 Sep  9 09:54 stafbacula.csr
-rw-------  1 bacula  bacula  1964 Sep  9 10:04 root.crt
-rw-------  1 bacula  bacula  1850 Sep  9 10:06 stafbacula.crt
$ 

Host file on the bacula jail

The hostname of the posgresql jail has to match with the CN of the server certificate. So we’ll add the hostname to /etc/hosts

1
root@stafbacula:~ # vi /etc/hosts
1
192.168.1.51    stafdb

Setup the bacula database

Create the bacula database user

1
2
3
4
5
6
7
8
9
[postgres@stafdb ~/data96]$ id
uid=770(postgres) gid=770(postgres) groups=770(postgres)
[postgres@stafdb ~/data96]$ psql postgres
psql (9.6.3)
Type "help" for help.

postgres=# create user bacula WITH PASSWORD 'xxxxxx';
CREATE ROLE
postgres=# 

To update the user password;

1
2
3
postgres=# alter user bacula PASSWORD 'yyyyyyy';
ALTER ROLE
postgres=# 

You can view the new permissions in the pg_user table or by execute the \du (describe user shortcut), by default the user has minimal permissions.

1
2
3
4
5
6
7
postgres=# select * from pg_user where usename = 'bacula';
 usename | usesysid | usecreatedb | usesuper | userepl | usebypassrls |  passwd  | valuntil | useconfig 
---------+----------+-------------+----------+---------+--------------+----------+----------+-----------
 bacula  |    16386 | f           | f        | f       | f            | ******** |          | 
(1 row)

postgres=# 
1
2
3
4
5
6
7
8
postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 bacula    |                                                            | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=# 

Allow the bacula user to create databases

The bacula database script will try to create the bacula catalog database. We’ll allow the bacula user to create databases,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
postgres=# alter user bacula CREATEDB;
ALTER ROLE
postgres=# select * from pg_user where usename = 'bacula';
 usename | usesysid | usecreatedb | usesuper | userepl | usebypassrls |  passwd  | valuntil | useconfig 
---------+----------+-------------+----------+---------+--------------+----------+----------+-----------
 bacula  |    16386 | t           | f        | f       | f            | ******** |          | 
(1 row)

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 bacula    | Create DB                                                  | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=# 

Create the bacula database

We’ll create a bacula database so we can verify the database connection from the bacula user to the bacula database.

Create a new bacula database

1
2
3
postgres=# create database bacula;
CREATE DATABASE
postgres=# 

Grant all permissions to the bacula user

1
2
3
postgres=# grant ALL on DATABASE bacula to bacula;
GRANT
postgres=# 

Update pg_hba

The pg_hba.conf configuration controls the Host Based Access to your postgreSQL database(s).

1
2
3
4
5
[postgres@stafdb ~/data96]$ pwd
/var/db/postgres/data96
[postgres@stafdb ~/data96]$ id
uid=770(postgres) gid=770(postgres) groups=770(postgres)
[postgres@stafdb ~/data96]$ vi pg_hba.conf 

And add the next lines;

1
2
3
4
5
# TYPE  DATABASE        USER            ADDRESS                 METHOD
hostssl bacula          bacula          192.168.1.52/32         md5 clientcert=1
hostssl template0       bacula          192.168.1.52/32         md5 clientcert=1
hostssl template1       bacula          192.168.1.52/32         md5 clientcert=1
hostssl postgres        bacula          192.168.1.52/32         md5 clientcert=1

Our bacula jail 192.168.1.52 only needs to have to the bacula database with the bacula user over ssl hostssl passwords will be send as a md5 hash and a client certificate is required clientcert=1.

We could also used the cert method and map the client certificate to postgresql user so we could authenticate with the client certificate only…

We allow access to the template* and the postgres database because it’s required for the bacula database xcreate script. We can remove them ( only allow access to the bacula database ) after the catalog database is created.

Restart postgresql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
root@stafdb:/var/db/postgres/data96 # service postgresql restart
DEBUG:  postgres: PostmasterMain: initial environment dump:
DEBUG:  -----------------------------------------
DEBUG:          LC_TIME=C
DEBUG:          LC_NUMERIC=C
DEBUG:          LC_MONETARY=C
DEBUG:          LC_MESSAGES=C
DEBUG:          LC_CTYPE=C
DEBUG:          LC_COLLATE=C
DEBUG:          MAIL=/var/mail/postgres
DEBUG:          PGLOCALEDIR=/usr/local/share/locale
DEBUG:          PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/var/db/postgres/bin
DEBUG:          PGDATA=/var/db/postgres/data96
DEBUG:          PWD=/var/db/postgres
DEBUG:          PGSYSCONFDIR=/usr/local/etc/postgresql
DEBUG:          HOME=/var/db/postgres
DEBUG:          USER=postgres
DEBUG:          SHELL=/bin/sh
DEBUG:          PG_GRANDPARENT_PID=79045
DEBUG:          BLOCKSIZE=K
DEBUG:  -----------------------------------------
LOG:  could not create IPv6 socket: Protocol not supported
LOG:  could not bind IPv4 socket: Address already in use
HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
WARNING:  could not create listen socket for "192.168.1.51"
DEBUG:  invoking IpcMemoryCreate(size=148480000)
DEBUG:  SlruScanDirectory invoking callback on pg_notify/0000
DEBUG:  removing file "pg_notify/0000"
DEBUG:  dynamic shared memory system will support 288 segments
DEBUG:  created dynamic shared memory control segment 773439544 (2316 bytes)
DEBUG:  max_safe_fds = 984, usable_fds = 1000, already_open = 6
LOG:  ending log output to stderr
HINT:  Future log output will go to log destination "syslog".
DEBUG:  CommitTransaction
DEBUG:  name: unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children: 
root@stafdb:/var/db/postgres/data96 #

Test the database connection

Verify

Verify the database connection for the bacula jail. See https://www.postgresql.org/docs/9.6/static/libpq-connect.html

1
2
3
4
5
6
7
8
9
10
[bacula@stafbacula /var/db/bacula/.postgres]$ psql "sslmode=verify-full host=stafdb dbname=bacula sslcert=`pwd`/postgresql.crt sslkey=`pwd`/postgresql.key sslrootcert=`pwd`/root.crt"
Password:
DEBUG:  CommitTransaction
DEBUG:  name: unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
psql (9.5.7, server 9.6.3)
WARNING: psql major version 9.5, server major version 9.6.
         Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
bacula=>

Create environment script

Bacula comes with a few scripts to popilate the catalog we will create an “environment” script to setup the required environment variabeles to connect to the database. https://www.postgresql.org/docs/9.6/static/libpq-envars.html gives an overview of PostgreSQL environment variabeles.

1
[bacula@stafbacula /var/db/bacula]$ vi psql_env.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
PGHOST=stafdb
PGUSER=bacula
PGSSLMODE=verify-full
PGSSLCERT=/var/db/bacula/.postgres/postgresql.crt
PGSSLKEY=/var/db/bacula/.postgres/postgresql.key
PGSSLROOTCERT=/var/db/bacula/.postgres/root.crt

export PGHOST
export PGUSER
export PGSSLMODE
export PGSSLCERT
export PGSSLKEY
export PGSSLROOTCERT

Test the environment script

1
2
3
4
5
6
7
8
9
10
11
12
13
root@stafbacula:~ # su -m bacula -c /bin/sh
$ . /var/db/bacula/psql_env.sh
$ psql bacula
Password: 
DEBUG:  CommitTransaction
DEBUG:  name: unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children: 
psql (9.5.8, server 9.6.4)
WARNING: psql major version 9.5, server major version 9.6.
         Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

bacula=> 

Configure the bacula catalog

Configuration directives

I found the bacula documention not very clear howto setup the catalog connection with certificate authentication - or I looked at the wrong place - so I downloaded the bacula source code ( version 7.4.7 )to verify the required directives. ./src/dird/d/dird_conf.c

1
[staf@vicky bacula-7.4.7]$ vim ./src/dird/dird_conf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*
   Bacula(R) - The Network Backup Solution

   Copyright (C) 2000-2016 Kern Sibbald

   The original author of Bacula is Kern Sibbald, with contributions
   from many others, a complete list can be found in the file AUTHORS.

   You may use this file and others of this release according to the
   license defined in the LICENSE file, which includes the Affero General
   Public License, v3.0 ("AGPLv3") and some additional permissions and
   terms pursuant to its AGPLv3 Section 7.

   This notice must be preserved when any source code is
   conveyed and/or propagated.

   Bacula(R) is a registered trademark of Kern Sibbald.
*/

<snip>

/*
 *    Catalog Resource Directives
 *
 *   name          handler     value                 code flags    default_value
 */
static RES_ITEM cat_items[] = {
   {"Name",     store_name,     ITEM(res_cat.hdr.name),    0, ITEM_REQUIRED, 0},
   {"Description", store_str,   ITEM(res_cat.hdr.desc),    0, 0, 0},
   {"dbaddress", store_str,     ITEM(res_cat.db_address),  0, 0, 0},
   {"Address",  store_str,      ITEM(res_cat.db_address),  0, 0, 0},
   {"DbPort",   store_pint32,   ITEM(res_cat.db_port),      0, 0, 0},
   /* keep this password as store_str for the moment */
   {"dbpassword", store_str,    ITEM(res_cat.db_password), 0, 0, 0},
   {"Password", store_str,      ITEM(res_cat.db_password), 0, 0, 0},
   {"dbuser",   store_str,      ITEM(res_cat.db_user),     0, 0, 0},
   {"User",     store_str,      ITEM(res_cat.db_user),     0, 0, 0},
   {"DbName",   store_str,      ITEM(res_cat.db_name),     0, ITEM_REQUIRED, 0},
   {"dbdriver", store_str,      ITEM(res_cat.db_driver),   0, 0, 0},
   {"DbSocket", store_str,      ITEM(res_cat.db_socket),   0, 0, 0},
   {"dbsslkey", store_str,      ITEM(res_cat.db_ssl_key),  0, 0, 0},
   {"dbsslcert", store_str,     ITEM(res_cat.db_ssl_cert),  0, 0, 0},
   {"dbsslca", store_str,       ITEM(res_cat.db_ssl_ca),  0, 0, 0},
   {"dbsslcapath", store_str,   ITEM(res_cat.db_ssl_capath),  0, 0, 0},
   {"dbsslcipher", store_str,   ITEM(res_cat.db_ssl_cipher),  0, 0, 0},
   /* Turned off for the moment */
   {"MultipleConnections", store_bit, ITEM(res_cat.mult_db_connections), 0, 0, 0},
   {"DisableBatchInsert", store_bool, ITEM(res_cat.disable_batch_insert), 0, ITEM_DEFAULT, false},
   {NULL, NULL, {0}, 0, 0, 0}
};

The ssl directives didn’t seem to work with postgresql :-( If we feed the postgresql environment variables with the correct ssl settings to the bacula director it seems to work.

Initialize the database

Drop the existing bacula database

The bacacla create script will try to create a new bacaula database so we’ll to drop or test database on our database server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@stafdb:~ # su - postgres
$ psql
psql (9.6.4)
Type "help" for help.

postgres=# drop database bacula ;
DROP DATABASE
postgres=# \l
                             List of databases
   Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   
-----------+----------+----------+---------+-------+-----------------------
 postgres  | postgres | UTF8     | C       | C     | 
 template0 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
(3 rows)

postgres=# 

Create the database

Logon the bacula jail and create the bacula database.

1
2
3
4
5
6
7
8
9
10
11
$ . /var/db/bacula/psql_env.sh
$ ./create_bacula_database
Creating postgresql database
Password: 
Password: 
CREATE DATABASE
ALTER DATABASE
Creation of bacula database succeeded.
Password: 
Password: 
Database encoding OK

Populate the bacula tables

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
$ ./make_bacula_tables 
Making postgresql tables
Password: 
CREATE TABLE
ALTER TABLE
CREATE INDEX
CREATE TABLE
ALTER TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
CREATE TABLE
CREATE TABLE
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
CREATE TABLE
CREATE INDEX
INSERT 0 1
Creation of Bacula PostgreSQL tables succeeded.
$ 

Verify

Logon the bacula database and verify that the database populated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$ psql
Password: 
psql (9.5.8, server 9.6.4)
WARNING: psql major version 9.5, server major version 9.6.
         Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

bacula=> \d
                       List of relations
 Schema |               Name                |   Type   | Owner  
--------+-----------------------------------+----------+--------
 public | basefiles                         | table    | bacula
 public | basefiles_baseid_seq              | sequence | bacula
 public | cdimages                          | table    | bacula
 public | client                            | table    | bacula
 public | client_clientid_seq               | sequence | bacula
 public | counters                          | table    | bacula
 public | device                            | table    | bacula
 public | device_deviceid_seq               | sequence | bacula
 public | file                              | table    | bacula
 public | file_fileid_seq                   | sequence | bacula
 public | filename                          | table    | bacula
 public | filename_filenameid_seq           | sequence | bacula
 public | fileset                           | table    | bacula
 public | fileset_filesetid_seq             | sequence | bacula
 public | job                               | table    | bacula
 public | job_jobid_seq                     | sequence | bacula
 public | jobhisto                          | table    | bacula
 public | jobmedia                          | table    | bacula
 public | jobmedia_jobmediaid_seq           | sequence | bacula
 public | location                          | table    | bacula
 public | location_locationid_seq           | sequence | bacula
 public | locationlog                       | table    | bacula
 public | locationlog_loclogid_seq          | sequence | bacula
 public | log                               | table    | bacula
 public | log_logid_seq                     | sequence | bacula
 public | media                             | table    | bacula
 public | media_mediaid_seq                 | sequence | bacula
 public | mediatype                         | table    | bacula
 public | mediatype_mediatypeid_seq         | sequence | bacula
 public | path                              | table    | bacula
 public | path_pathid_seq                   | sequence | bacula
 public | pathhierarchy                     | table    | bacula
 public | pathvisibility                    | table    | bacula
 public | pool                              | table    | bacula
 public | pool_poolid_seq                   | sequence | bacula
 public | restoreobject                     | table    | bacula
 public | restoreobject_restoreobjectid_seq | sequence | bacula
 public | snapshot                          | table    | bacula
 public | snapshot_snapshotid_seq           | sequence | bacula
--More--(byte 2667)

Cleanup

Disable the access to template? and postgres databases.

1
root@stafdb:/var/db/postgres/data96 # vi pg_hba.conf
1
2
3
4
5
host    all             all             ::1/128                 trust
hostssl bacula          bacula          192.168.1.52/32         md5 clientcert=1
# hostssl       template0       bacula          192.168.1.52/32         md5 clientcert=1
# hostssl       template1       bacula          192.168.1.52/32         md5 clientcert=1
# hostssl       postgres        bacula          192.168.1.52/32         md5 clientcert=1

Reload

1
2
root@stafdb:/var/db/postgres/data96 # service postgresql reload
root@stafdb:/var/db/postgres/data96 # 

Test it. Verify that access to the postgres database is denied from the bacula host.

1
2
3
$ psql postgres
psql: FATAL:  no pg_hba.conf entry for host "192.168.1.52", user "bacula", database "postgres", SSL on
$ 

Bacula catalog configuration

Update the bacula director configuration

1
root@stafbacula:/usr/local/etc/bacula # vi bacula-dir.conf
1
2
3
4
5
6
7
8
# Generic catalog service
Catalog { 
  Name = MyCatalog
  dbname = "bacula"; dbuser = "bacula"; dbpassword = "********" ; dbsslkey = "/var/db/bacula/.postgres
/postgresql.key"; dbsslcert = "/var/db/bacula/.postgres/postgresql.crt"; dbsslca= "/var/db/bacula/.postgres
/root.crt"

}

Test the catalog connection

bacula include a program to verify the bacula catalog “dbcheck”, the -c switch select the bacula director configuration file the -B switch print out the configuration.

1
2
3
4
5
6
7
8
9
10
11
12
bacula@stafbacula /usr/local]$ dbcheck -c /usr/local/etc/bacula/bacula-dir.conf -B -v
catalog=MyCatalog
db_name=bacula
db_driver=
db_user=bacula
db_password=*******
db_address=stafdb
db_port=0
db_socket=
db_type=PostgreSQL
working_dir=/var/db/bacula
[bacula@stafbacula /usr/local]$ 

For some reason the ssl directives aren’t include and the connection fails

1
2
3
4
5
6
7
8
[bacula@stafbacula /usr/local/etc/rc.d]$ dbcheck -c /usr/local/etc/bacula/bacula-dir.conf -v
dbcheck: Fatal Error at dbcheck.c:303 because:
postgresql.c:271 Unable to connect to PostgreSQL server. Database=bacula User=bacula
Possible causes: SQL server not running; password incorrect; max_connections exceeded.
09-Sep 14:22 dbcheck: Fatal Error at dbcheck.c:303 because:
postgresql.c:271 Unable to connect to PostgreSQL server. Database=bacula User=bacula
Possible causes: SQL server not running; password incorrect; max_connections exceeded.
[bacula@stafbacula /usr/local/etc/rc.d]$ 

On our postgres host we get the error message that the bacula host tries to connect without SSL.

1
2
3
4
5
6
7
8
9
10
11
oot@stafdb:/var/db/postgres/data96 # tail -f /var/log/messages
Sep  9 14:22:10 stafdb postgres[14183]: [10-1] FATAL:  connection requires a valid client certificate
Sep  9 14:22:10 stafdb postgres[14184]: [10-1] FATAL:  no pg_hba.conf entry for host "192.168.1.52", user "bacula", database "bacula", SSL off
Sep  9 14:22:15 stafdb postgres[14185]: [10-1] FATAL:  connection requires a valid client certificate
Sep  9 14:22:15 stafdb postgres[14186]: [10-1] FATAL:  no pg_hba.conf entry for host "192.168.1.52", user "bacula", database "bacula", SSL off
Sep  9 14:22:20 stafdb postgres[14187]: [10-1] FATAL:  connection requires a valid client certificate
Sep  9 14:22:20 stafdb postgres[14188]: [10-1] FATAL:  no pg_hba.conf entry for host "192.168.1.52", user "bacula", database "bacula", SSL off
Sep  9 14:22:25 stafdb postgres[14190]: [10-1] FATAL:  connection requires a valid client certificate
Sep  9 14:22:25 stafdb postgres[14191]: [10-1] FATAL:  no pg_hba.conf entry for host "192.168.1.52", user "bacula", database "bacula", SSL off
Sep  9 14:22:30 stafdb postgres[14193]: [10-1] FATAL:  connection requires a valid client certificate
Sep  9 14:22:30 stafdb postgres[14194]: [10-1] FATAL:  no pg_hba.conf entry for host "192.168.1.52", user "bacula", database "bacula", SSL off

When set the postgresql varialables with the correct ssl settings the connnection works fine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[bacula@stafbacula /usr/local/etc/rc.d]$ dbcheck -c /usr/local/etc/bacula/bacula-dir.conf -v
Hello, this is the database check/correct program.
Modify database is off. Verbose is on.
Please select the function you want to perform.

     1) Toggle modify database flag
     2) Toggle verbose flag
     3) Check for bad Filename records
     4) Check for bad Path records
     5) Check for duplicate Filename records
     6) Check for duplicate Path records
     7) Check for orphaned Jobmedia records
     8) Check for orphaned File records
     9) Check for orphaned Path records
    10) Check for orphaned Filename records
    11) Check for orphaned FileSet records
    12) Check for orphaned Client records
    13) Check for orphaned Job records
    14) Check for all Admin records
    15) Check for all Restore records
    16) All (3-15)
    17) Quit
Select function number: 

Bacula director

Enable the bacula director

1
2
3
root@stafbacula:/usr/local/etc/rc.d # sysrc bacula_dir_enable=yes
bacula_dir_enable:  -> yes
root@stafbacula:/usr/local/etc/rc.d # 

Create the bacula.log

1
2
root@stafbacula:/var/log # touch /var/log/bacula.log
root@stafbacula:/var/log # chown bacula:bacula /var/log/bacula.log

Include the postgreSQL ssl settings in the bacula director startup script

Update the bacula-dir startup sript to include the ssl settings.

1
2
3
4
5
6
7
8
9
10
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
# bacula_dir_enable  (bool):   Set to NO by default.
#                Set it to YES to enable bacula_dir.
# bacula_dir_flags (params):   Set params used to start bacula_dir.
#

. /etc/rc.subr
. /var/db/bacula/psql_env.sh

bconsole access

To test that the catalog works correctly with the director we need to setup bconsole access. Open the bacula director configuration file.

1
[root@stafbacula /usr/local/etc/bacula]# vim bacula-dir.conf

And defined and Password

1
2
3
4
5
6
7
8
9
10
Director {                            # define myself
  Name = MyBaculaDirector
  DIRport = 9101                # where we listen for UA connections
  QueryFile = "/usr/local/share/bacula/query.sql"
  WorkingDirectory = "/var/db/bacula"
  PidDirectory = "/var/run"
  Maximum Concurrent Jobs = 20
  Password = "*******"         # Console password
  Messages = Daemon
}

Open the bconsole configuration file

1
[root@stafbacula /usr/local/etc/bacula]# vi bconsole.conf

and setup the same password

1
2
3
4
5
6
7
8
9
10
11
12
# Bacula User Agent (or Console) Configuration File
#
# Copyright (C) 2000-2015 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#

Director {
  Name = MyBaculaDirector
  DIRport = 9101
  address = localhost
  Password = "*****"
}

Start the director & test

Start the bacula-dir service

1
2
3
4
5
6
7
root@stafbacula /usr/local/etc/bacula]# service bacula-dir start
Starting bacula_dir.
[root@stafbacula /usr/local/etc/bacula]# ps aux | grep -i bacula 
bacula 14416  0.0  0.1 51424 6588  -  SsJ  14:40   0:00.12 /usr/local/sbin/bacula-dir -u bacula -g bacula 
root   14420  0.0  0.0 14796 1968  0  R+J  14:40   0:00.00 grep -i bacula
root   13530  0.0  0.0  8300 1596  2  I+J  13:47   0:00.00 tail -f /var/log/bacula.log
[root@stafbacula /usr/local/etc/bacula]#

And test the console access

1
2
3
4
5
6
7
8
bacula@stafbacula:/usr/local/etc/bacula % bconsole
Connecting to Director localhost:9101
1000 OK: 102 MyBaculaDirector Version: 7.4.7 (16 March 2017)
Enter a period to cancel a command.
*version
MyBaculaDirector Version: 7.4.7 (16 March 2017) amd64-portbld-freebsd11.0 freebsd 11.0-RELEASE-p12 
You have messages.
*

In a next blog post we’ll continue with the bacula configuration.

Have fun!

Links

Comments