Skip to content

Commit aee6781

Browse files
committed
fix(main): exclude MariaDB user roles and support zero-config TLS
1 parent f715c47 commit aee6781

3 files changed

Lines changed: 87 additions & 7 deletions

File tree

Changelog

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
- fix(main): calculate health score early in historical comparison to ensure scores exist for trend analysis.
3737
- fix(main): calculate query cache efficiency using Com_select on MariaDB (MDEV-4981)
3838
- fix(main): calculate query cache efficiency using Com_select on MariaDB, where Com_select includes query cache hits (MDEV-4981).
39-
- fix(main): exclude MariaDB user roles from remote user SSL enforcement audit
39+
- fix(main): exclude MariaDB user roles from SSL remote user audit
4040
- fix(main): format YAML null as tilde (~) and multiline values using literal block style.
4141
- fix(main): guard InnoDB log file size and log size percentage checks against uninitialized variables.
4242
- fix(main): guard version and version comment checks in MariaDB parallel replication and query cache blocks.

mysqltuner.pl

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5051,12 +5051,17 @@ sub ssl_tls_recommendations {
50515051

50525052
# Certificate presence and local audit
50535053
if ( !$myvar{'ssl_cert'} && !$myvar{'ssl_key'} ) {
5054-
badprint "No SSL certificates configured (ssl_cert/ssl_key are empty)";
5055-
push_recommendation( 'Security',
5054+
if ( mysql_version_ge( 11, 4 ) && $myvar{'version'} =~ /MariaDB/i && ( defined($myvar{'have_ssl'}) && ($myvar{'have_ssl'} eq 'YES' || $myvar{'have_ssl'} eq 'ON') ) ) {
5055+
goodprint "TLS is active, but no explicit ssl_cert/ssl_key paths are configured (MariaDB zero-configuration TLS active)";
5056+
}
5057+
else {
5058+
badprint "No SSL certificates configured (ssl_cert/ssl_key are empty)";
5059+
push_recommendation( 'Security',
50565060
"Configure SSL certificates (ssl_cert, ssl_key, ssl_ca) to enable encrypted connections."
5057-
);
5058-
push @ssl_csv_rows,
5061+
);
5062+
push @ssl_csv_rows,
50595063
"ssl_cert/ssl_key,empty,NoCertificates,Configure SSL certificates (ssl_cert, ssl_key, ssl_ca) to enable encrypted connections.";
5064+
}
50605065
}
50615066
else {
50625067
check_local_certificates( \@ssl_csv_rows );
@@ -5211,12 +5216,19 @@ sub check_remote_user_ssl {
52115216
my @remote_users;
52125217
if ( mysql_version_ge( 10, 4 ) && $myvar{'version'} =~ /MariaDB/i ) {
52135218
@remote_users = select_array(
5214-
"SELECT CONCAT(QUOTE(user), '\@', QUOTE(host)) FROM mysql.global_priv WHERE host NOT IN ('localhost', '127.0.0.1', '::1') AND JSON_VALUE(Priv, '\$.ssl_type') = ''"
5219+
"SELECT CONCAT(QUOTE(user), '\@', QUOTE(host)) FROM mysql.global_priv WHERE host NOT IN ('localhost', '127.0.0.1', '::1') AND JSON_VALUE(Priv, '\$.ssl_type') = '' AND COALESCE(JSON_VALUE(Priv, '\$.is_role'), '') NOT IN ('true', '1')"
52155220
);
52165221
}
52175222
else {
5223+
my $is_role_column = select_one(
5224+
"select count(*) from information_schema.columns where TABLE_NAME='user' AND TABLE_SCHEMA='mysql' and COLUMN_NAME='IS_ROLE'"
5225+
);
5226+
my $extra_user_condition = "";
5227+
if ( defined($is_role_column) && $is_role_column =~ /^\d+$/ && $is_role_column > 0 ) {
5228+
$extra_user_condition = " AND IS_ROLE = 'N'";
5229+
}
52185230
@remote_users = select_array(
5219-
"SELECT CONCAT(QUOTE(user), '\@', QUOTE(host)) FROM mysql.user WHERE host NOT IN ('localhost', '127.0.0.1', '::1') AND (ssl_type = 'NONE' OR ssl_type = '')"
5231+
"SELECT CONCAT(QUOTE(user), '\@', QUOTE(host)) FROM mysql.user WHERE host NOT IN ('localhost', '127.0.0.1', '::1') AND (ssl_type = 'NONE' OR ssl_type = '')$extra_user_condition"
52205232
);
52215233
}
52225234

tests/ssl_tls_validation.t

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,31 @@ subtest 'ssl_tls_recommendations' => sub {
115115
main::ssl_tls_recommendations();
116116
ok(grep(/Insecure TLS versions enabled/, @bad_prints), "Detects TLS 1.1 as insecure");
117117
ok(grep(/No modern TLS versions/, @bad_prints), "Detects lack of TLS 1.2+");
118+
119+
# Case 5: MariaDB 11.4+ Zero-Configuration TLS (ssl_cert and ssl_key empty, but TLS active)
120+
MySQLTuner::TestHelper::reset_state();
121+
%main::myvar = ( %main::myvar,
122+
'version' => '11.8.8-MariaDB',
123+
'have_ssl' => 'YES',
124+
'require_secure_transport' => 'ON',
125+
'tls_version' => 'TLSv1.2,TLSv1.3',
126+
'ssl_cert' => '',
127+
'ssl_key' => ''
128+
);
129+
local *main::select_one = sub {
130+
my $query = shift;
131+
if ($query =~ /Ssl_cipher/) {
132+
return "Ssl_cipher\tTLS_AES_256_GCM_SHA384";
133+
}
134+
return "";
135+
};
136+
@main::generalrec = ();
137+
@bad_prints = ();
138+
@good_prints = ();
139+
@recommendations = ();
140+
main::ssl_tls_recommendations();
141+
ok(grep(/TLS is active, but no explicit ssl_cert\/ssl_key paths are configured/, @good_prints), "MariaDB 11.4+ Zero-Configuration TLS prints info message");
142+
is(scalar(grep(/No SSL certificates configured/, @bad_prints)), 0, "No missing certificates warning for zero-config TLS");
118143
};
119144

120145
subtest 'check_local_certificates' => sub {
@@ -217,6 +242,49 @@ subtest 'check_remote_user_ssl' => sub {
217242
@bad_prints = ();
218243
main::check_remote_user_ssl();
219244
ok(grep(/users can connect remotely without SSL/, @bad_prints), "Detects remote user without SSL (MySQL)");
245+
246+
# Case 3: Exclude role (MariaDB >= 10.4)
247+
MySQLTuner::TestHelper::reset_state();
248+
%main::myvar = ( %main::myvar, 'version' => '10.5.0-MariaDB' );
249+
local *main::select_array = sub {
250+
my ($query) = @_;
251+
if ($query =~ /global_priv/ && $query =~ /is_role/) {
252+
return (); # Excluded!
253+
}
254+
return ("'should_not_happen'\@'%'");
255+
};
256+
local *main::mysql_version_ge = sub { 1 };
257+
@bad_prints = ();
258+
@good_prints = ();
259+
main::check_remote_user_ssl();
260+
ok(grep(/All remote users have SSL enforcement active/, @good_prints), "Excludes role (MariaDB >= 10.4)");
261+
262+
# Case 4: Exclude role (MariaDB < 10.4 with IS_ROLE column)
263+
MySQLTuner::TestHelper::reset_state();
264+
%main::myvar = ( %main::myvar, 'version' => '10.2.0-MariaDB' );
265+
local *main::select_one = sub {
266+
my ($query) = @_;
267+
if ($query =~ /IS_ROLE/) {
268+
return 1; # IS_ROLE column exists
269+
}
270+
return 0;
271+
};
272+
local *main::select_array = sub {
273+
my ($query) = @_;
274+
if ($query =~ /mysql.user/ && $query =~ /IS_ROLE = 'N'/) {
275+
return (); # Excluded!
276+
}
277+
return ("'should_not_happen'\@'%'");
278+
};
279+
local *main::mysql_version_ge = sub {
280+
my ($maj, $min) = @_;
281+
if ($maj == 10 && $min == 4) { return 0; } # Not >= 10.4
282+
return 1;
283+
};
284+
@bad_prints = ();
285+
@good_prints = ();
286+
main::check_remote_user_ssl();
287+
ok(grep(/All remote users have SSL enforcement active/, @good_prints), "Excludes role using IS_ROLE (MariaDB < 10.4)");
220288
};
221289

222290
done_testing();

0 commit comments

Comments
 (0)