]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1885709: Allow connecting to MySQL via SSL (#109)
authorDave Miller <justdave@bugzilla.org>
Sun, 17 Mar 2024 04:10:20 +0000 (00:10 -0400)
committerGitHub <noreply@github.com>
Sun, 17 Mar 2024 04:10:20 +0000 (00:10 -0400)
* Bug 1885709: Allow connecting to MySQL via SSL

Bugzilla/DB/Mysql.pm
Bugzilla/DaemonControl.pm
Bugzilla/Install/Localconfig.pm
conf/checksetup_answers.txt
template/en/default/setup/strings.txt.pl

index 9cc781bc1ec884230017f0b6dc4225a9785a6deb..484c1355e4527cddab8210662b5d3a8ee8d3546a 100644 (file)
@@ -55,6 +55,19 @@ sub BUILDARGS {
 
   my %attrs = (mysql_enable_utf8 => 1);
 
+  # MySQL SSL options
+  my ($ssl_ca_file, $ssl_ca_path, $ssl_cert, $ssl_key, $ssl_pubkey) =
+    @$params{qw(db_mysql_ssl_ca_file db_mysql_ssl_ca_path
+                db_mysql_ssl_client_cert db_mysql_ssl_client_key db_mysql_ssl_get_pubkey)};
+  if ($ssl_ca_file || $ssl_ca_path || $ssl_cert || $ssl_key || $ssl_pubkey) {
+    $attrs{'mysql_ssl'}               = 1;
+    $attrs{'mysql_ssl_ca_file'}       = $ssl_ca_file if $ssl_ca_file;
+    $attrs{'mysql_ssl_ca_path'}       = $ssl_ca_path if $ssl_ca_path;
+    $attrs{'mysql_ssl_client_cert'}   = $ssl_cert    if $ssl_cert;
+    $attrs{'mysql_ssl_client_key'}    = $ssl_key     if $ssl_key;
+    $attrs{'mysql_get_server_pubkey'} = $ssl_pubkey  if $ssl_pubkey;
+  }
+
   return {dsn => $dsn, user => $user, pass => $pass, attrs => \%attrs};
 }
 
index 8c352941e8faced681d518fa2f1431f0160fdd6c..7cf79ffb16f713e025bb52d26b90f750d4bc449c 100644 (file)
@@ -15,7 +15,7 @@ use Bugzilla::Constants qw(bz_locations);
 use Cwd qw(realpath);
 use English qw(-no_match_vars $PROGRAM_NAME);
 use File::Spec::Functions qw(catfile catdir);
-use Future::Utils qw(repeat try_repeat);
+use Future::Utils qw(repeat try_repeat_until_success);
 use Future;
 use IO::Async::Loop;
 use IO::Async::Process;
@@ -222,6 +222,7 @@ sub assert_connect {
 }
 
 sub assert_database {
+  my $assert_dbierrstr = "";
   my $loop = IO::Async::Loop->new;
   my $lc   = Bugzilla::Install::Localconfig::read_localconfig();
 
@@ -230,23 +231,38 @@ sub assert_database {
   }
 
   my $dsn    = "dbi:mysql:database=$lc->{db_name};host=$lc->{db_host}";
-  my $repeat = repeat {
+  my $repeat = try_repeat_until_success {
     $loop->delay_future(after => 0.25)->then(sub {
-      my $dbh
-        = DBI->connect($dsn, $lc->{db_user}, $lc->{db_pass},
-        {RaiseError => 0, PrintError => 0},
-        );
+      my $attrs = {RaiseError => 1, PrintError => 1};
+      my ($ssl_ca_file, $ssl_ca_path, $ssl_cert, $ssl_key, $ssl_pubkey) =
+        @$lc{qw(db_mysql_ssl_ca_file db_mysql_ssl_ca_path
+                db_mysql_ssl_client_cert db_mysql_ssl_client_key db_mysql_ssl_get_pubkey)};
+      if ($ssl_ca_file || $ssl_ca_path || $ssl_cert || $ssl_key || $ssl_pubkey) {
+        $attrs->{'mysql_ssl'}               = 1;
+        $attrs->{'mysql_ssl_ca_file'}       = $ssl_ca_file if $ssl_ca_file;
+        $attrs->{'mysql_ssl_ca_path'}       = $ssl_ca_path if $ssl_ca_path;
+        $attrs->{'mysql_ssl_client_cert'}   = $ssl_cert    if $ssl_cert;
+        $attrs->{'mysql_ssl_client_key'}    = $ssl_key     if $ssl_key;
+        $attrs->{'mysql_get_server_pubkey'} = $ssl_pubkey  if $ssl_pubkey;
+      }
+      my $dbh;
+      eval {
+        $dbh
+        = DBI->connect($dsn, $lc->{db_user}, $lc->{db_pass}, $attrs);
+      };
+      if ($!) { $assert_dbierrstr = $@; die $@; }
+      $assert_dbierrstr = DBI->errstr() || '';
+      die "$assert_dbierrstr" if $assert_dbierrstr;
       Future->wrap($dbh);
     });
-  }
-  until => sub { defined shift->get };
+  };
 
   my $timeout
     = $loop->timeout_future(after => 20)->else_fail('assert_database timeout');
   my $any_f = Future->wait_any($repeat, $timeout);
   return $any_f->transform(
     done => sub {return},
-    fail => sub {"unable to connect to $dsn as $lc->{db_user}"},
+    fail => sub {"unable to connect to $dsn as $lc->{db_user}: $assert_dbierrstr"},
   );
 }
 
index c4c249709d2b8565ea5455157e16c7c5d4092ec1..4a19b2c3611081dcc0569dc6cad06a89b9ed5e44 100644 (file)
@@ -68,6 +68,11 @@ use constant LOCALCONFIG_VARS => (
   {name => 'db_port',      default => 0,},
   {name => 'db_sock',      default => '',},
   {name => 'db_check',     default => 1,},
+  {name => 'db_mysql_ssl_ca_file',     default => '',},
+  {name => 'db_mysql_ssl_ca_path',     default => '',},
+  {name => 'db_mysql_ssl_client_cert', default => '',},
+  {name => 'db_mysql_ssl_client_key',  default => '',},
+  {name => 'db_mysql_ssl_get_pubkey',  default => 0,},
   {name => 'index_html',   default => 0,},
   {name => 'cvsbin',       default => sub { bin_loc('cvs') },},
   {name => 'interdiffbin', default => sub { bin_loc('interdiff') },},
index b83f6d0ba32d98ee2314e3d5a151e6cea4373b70..2c8e7e6b7c6d6b7bb40d88ca0b91fca7248f6af2 100644 (file)
@@ -27,3 +27,4 @@ $answer{'defaultpriority'}      = '--';
 $answer{'defaultseverity'}      = 'normal';
 $answer{'skin'}                 = 'Mozilla';
 $answer{'docs_urlbase'}         = 'https://bmo.readthedocs.io/en/latest/';
+$answer{'db_mysql_ssl_get_pubkey'} = 1;
index 2b47653bffdd5853bcaf10aca07a1e2c9eefad42..851be09df8c92f8eb17ece1f5ad6e334f97e4df5 100644 (file)
@@ -178,6 +178,26 @@ blank, then MySQL's compiled-in default will be used. You probably
 want that.
 END
   localconfig_db_user  => "Who we connect to the database as.",
+  localconfig_db_mysql_ssl_ca_file => <<'END',
+Path to a PEM file with a list of trusted SSL CA certificates.
+The file must be readable by web server user.
+END
+  localconfig_db_mysql_ssl_ca_path => <<'END',
+Path to a directory containing trusted SSL CA certificates in PEM format.
+Directory and files inside must be readable by the web server user.
+END
+  localconfig_db_mysql_ssl_client_cert => <<'END',
+Full path to the client SSL certificate in PEM format we will present to the DB server.
+The file must be readable by web server user.
+END
+  localconfig_db_mysql_ssl_client_key => <<'END',
+Full path to the private key corresponding to the client SSL certificate.
+The file must not be password-protected and must be readable by web server user.
+END
+  localconfig_db_mysql_ssl_get_pubkey => <<'END',
+Whether to have Bugzilla automatically fetch the public key from the server at connection time.
+This is less secure than specifying the ca_file above.
+END
   localconfig_diffpath => <<'END',
 For the "Difference Between Two Patches" feature to work, we need to know
 what directory the "diff" bin is in. (You only need to set this if you