Skip to content

Commit acead3a

Browse files
committed
ssl tests and CACertificateFile docs
1 parent d7a6d8d commit acead3a

File tree

7 files changed

+139
-65
lines changed

7 files changed

+139
-65
lines changed
3.95 KB
Binary file not shown.

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@
1212
*.ttf binary
1313
*.woff binary
1414
*.woff2 binary
15+
*.pfx binary
16+

docs/content/connection-options.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,18 @@ These are the options that need to be used in order to configure a connection to
7878
<tr>
7979
<td>Certificate File, CertificateFile</td>
8080
<td></td>
81-
<td>This option specifies the path to a certificate file in PKCS #12 format (.pfx). </td>
81+
<td>This option specifies the path to a certificate file in a PEM Encoded (.pem) or PKCS #12 (.pfx) format. </td>
8282
</tr>
8383
<tr>
8484
<td>Certificate Password, CertificatePassword </td>
8585
<td></td>
8686
<td>Specifies a password that is used in conjunction with a certificate specified using the option CertificateFile. Not required if the certificate file is not password protected.</td>
8787
</tr>
88+
<tr>
89+
<td>CA Certificate File, CACertificateFile</td>
90+
<td></td>
91+
<td>This option specifies the path to a CA certificate file in a PEM Encoded (.pem) format. This should be used in with <code>SslMode=VerifyCA</code> or <code>SslMode=VerifyFull</code> to enable verification of a CA certificate that is not trusted by the Operating System's certificate store.</td>
92+
</tr>
8893
</table>
8994

9095
Connection Pooling Options

tests/MySqlConnector.Tests/MySqlConnectionStringBuilderTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public void Defaults()
2828
Assert.Equal(false, csb.BufferResultSets);
2929
Assert.Equal(180u, csb.ConnectionIdleTimeout);
3030
Assert.Equal(false, csb.ForceSynchronous);
31+
Assert.Equal(null, csb.CACertificateFile);
3132
#endif
3233
Assert.Equal(0u, csb.Keepalive);
3334
Assert.Equal(100u, csb.MaximumPoolSize);
@@ -70,6 +71,7 @@ public void ParseConnectionString()
7071
"connectionidletimeout=30;" +
7172
"bufferresultsets=true;" +
7273
"forcesynchronous=true;" +
74+
"ca certificate file=ca.pem;" +
7375
#endif
7476
"Keep Alive=90;" +
7577
"minpoolsize=5;" +
@@ -98,6 +100,7 @@ public void ParseConnectionString()
98100
Assert.Equal(true, csb.BufferResultSets);
99101
Assert.Equal(30u, csb.ConnectionIdleTimeout);
100102
Assert.Equal(true, csb.ForceSynchronous);
103+
Assert.Equal("ca.pem", csb.CACertificateFile);
101104
#endif
102105
Assert.Equal(90u, csb.Keepalive);
103106
Assert.Equal(15u, csb.MaximumPoolSize);

tests/SideBySide/Attributes.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,14 @@ public SslRequiredConnectionFactAttribute()
107107
Skip = "SSL not explicitly required";
108108
}
109109
}
110+
111+
public class SslRequiredConnectionTheoryAttribute : TheoryAttribute
112+
{
113+
public SslRequiredConnectionTheoryAttribute()
114+
{
115+
var csb = AppConfig.CreateConnectionStringBuilder();
116+
if(csb.SslMode == MySqlSslMode.None || csb.SslMode == MySqlSslMode.Preferred)
117+
Skip = "SSL not explicitly required";
118+
}
119+
}
110120
}

tests/SideBySide/ConnectAsync.cs

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -115,70 +115,6 @@ public async Task ConnectKeepAlive()
115115
}
116116
}
117117

118-
[SslRequiredConnectionFact]
119-
public async Task ConnectSslPreferred()
120-
{
121-
var csb = AppConfig.CreateConnectionStringBuilder();
122-
string requiredSslVersion;
123-
using (var connection = new MySqlConnection(csb.ConnectionString))
124-
{
125-
using (var cmd = connection.CreateCommand())
126-
{
127-
await connection.OpenAsync();
128-
cmd.CommandText = "SHOW SESSION STATUS LIKE 'Ssl_version'";
129-
requiredSslVersion = (string)await cmd.ExecuteScalarAsync();
130-
}
131-
}
132-
Assert.False(string.IsNullOrWhiteSpace(requiredSslVersion));
133-
134-
csb.SslMode = MySqlSslMode.Preferred;
135-
using (var connection = new MySqlConnection(csb.ConnectionString))
136-
{
137-
using (var cmd = connection.CreateCommand())
138-
{
139-
await connection.OpenAsync();
140-
cmd.CommandText = "SHOW SESSION STATUS LIKE 'Ssl_version'";
141-
var preferredSslVersion = (string)await cmd.ExecuteScalarAsync();
142-
Assert.Equal(requiredSslVersion, preferredSslVersion);
143-
}
144-
}
145-
}
146-
147-
[SslRequiredConnectionFact]
148-
public async Task ConnectSslClientCertificate()
149-
{
150-
var csb = AppConfig.CreateConnectionStringBuilder();
151-
csb.CertificateFile = Path.Combine(AppConfig.CertsPath, "ssl-client.pfx");
152-
csb.CertificatePassword = "";
153-
using (var connection = new MySqlConnection(csb.ConnectionString))
154-
{
155-
using (var cmd = connection.CreateCommand())
156-
{
157-
await connection.OpenAsync();
158-
cmd.CommandText = "SHOW SESSION STATUS LIKE 'Ssl_version'";
159-
var sslVersion = (string)await cmd.ExecuteScalarAsync();
160-
Assert.False(string.IsNullOrWhiteSpace(sslVersion));
161-
}
162-
}
163-
}
164-
165-
[SslRequiredConnectionFact]
166-
public async Task ConnectSslBadClientCertificate()
167-
{
168-
var csb = AppConfig.CreateConnectionStringBuilder();
169-
csb.CertificateFile = Path.Combine(AppConfig.CertsPath, "non-ca-client.pfx");
170-
csb.CertificatePassword = "";
171-
using (var connection = new MySqlConnection(csb.ConnectionString))
172-
{
173-
#if BASELINE
174-
var exType = typeof(IOException);
175-
#else
176-
var exType = typeof(MySqlException);
177-
#endif
178-
await Assert.ThrowsAsync(exType, async () => await connection.OpenAsync());
179-
}
180-
}
181-
182118
[Fact]
183119
public async Task ConnectionDatabase()
184120
{

tests/SideBySide/SslTests.cs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
using System;
2+
using System.Data;
3+
using System.IO;
4+
using System.Threading.Tasks;
5+
using MySql.Data.MySqlClient;
6+
using Xunit;
7+
8+
namespace SideBySide
9+
{
10+
public class SslTests : IClassFixture<DatabaseFixture>
11+
{
12+
public SslTests(DatabaseFixture database)
13+
{
14+
m_database = database;
15+
}
16+
17+
[SslRequiredConnectionFact]
18+
public async Task ConnectSslPreferred()
19+
{
20+
var csb = AppConfig.CreateConnectionStringBuilder();
21+
string requiredSslVersion;
22+
using (var connection = new MySqlConnection(csb.ConnectionString))
23+
{
24+
using (var cmd = connection.CreateCommand())
25+
{
26+
await connection.OpenAsync();
27+
cmd.CommandText = "SHOW SESSION STATUS LIKE 'Ssl_version'";
28+
requiredSslVersion = (string)await cmd.ExecuteScalarAsync();
29+
}
30+
}
31+
Assert.False(string.IsNullOrWhiteSpace(requiredSslVersion));
32+
33+
csb.SslMode = MySqlSslMode.Preferred;
34+
using (var connection = new MySqlConnection(csb.ConnectionString))
35+
{
36+
using (var cmd = connection.CreateCommand())
37+
{
38+
await connection.OpenAsync();
39+
cmd.CommandText = "SHOW SESSION STATUS LIKE 'Ssl_version'";
40+
var preferredSslVersion = (string)await cmd.ExecuteScalarAsync();
41+
Assert.Equal(requiredSslVersion, preferredSslVersion);
42+
}
43+
}
44+
}
45+
46+
[SslRequiredConnectionTheory]
47+
[InlineData("ssl-client.pfx", null, null)]
48+
[InlineData("ssl-client-pw-test.pfx", "test", null)]
49+
[InlineData("ssl-client-cert.pem", null, null)]
50+
#if !BASELINE
51+
[InlineData("ssl-client.pfx", null, "ssl-ca-cert.pem")]
52+
[InlineData("ssl-client-pw-test.pfx", "test", "ssl-ca-cert.pem")]
53+
[InlineData("ssl-client-cert.pem", null, "ssl-ca-cert.pem")]
54+
#endif
55+
public async Task ConnectSslClientCertificate(string certFile, string certFilePassword, string caCertFile)
56+
{
57+
var csb = AppConfig.CreateConnectionStringBuilder();
58+
csb.CertificateFile = Path.Combine(AppConfig.CertsPath, certFile);
59+
csb.CertificatePassword = certFilePassword;
60+
if (caCertFile != null)
61+
{
62+
csb.SslMode = MySqlSslMode.VerifyCA;
63+
#if !BASELINE
64+
csb.CACertificateFile = Path.Combine(AppConfig.CertsPath, caCertFile);
65+
#endif
66+
}
67+
using (var connection = new MySqlConnection(csb.ConnectionString))
68+
{
69+
using (var cmd = connection.CreateCommand())
70+
{
71+
await connection.OpenAsync();
72+
cmd.CommandText = "SHOW SESSION STATUS LIKE 'Ssl_version'";
73+
var sslVersion = (string)await cmd.ExecuteScalarAsync();
74+
Assert.False(string.IsNullOrWhiteSpace(sslVersion));
75+
}
76+
}
77+
}
78+
79+
[SslRequiredConnectionFact]
80+
public async Task ConnectSslBadClientCertificate()
81+
{
82+
var csb = AppConfig.CreateConnectionStringBuilder();
83+
csb.CertificateFile = Path.Combine(AppConfig.CertsPath, "non-ca-client.pfx");
84+
csb.CertificatePassword = "";
85+
using (var connection = new MySqlConnection(csb.ConnectionString))
86+
{
87+
#if BASELINE
88+
var exType = typeof(IOException);
89+
#else
90+
var exType = typeof(MySqlException);
91+
#endif
92+
await Assert.ThrowsAsync(exType, async () => await connection.OpenAsync());
93+
}
94+
}
95+
96+
#if BASELINE
97+
[Fact(Skip = "MySql.Data does not support CACertificateFile")]
98+
#else
99+
[SslRequiredConnectionFact]
100+
#endif
101+
public async Task ConnectSslBadCaCertificate()
102+
{
103+
var csb = AppConfig.CreateConnectionStringBuilder();
104+
csb.CertificateFile = Path.Combine(AppConfig.CertsPath, "ssl-client-cert.pem");
105+
csb.SslMode = MySqlSslMode.VerifyCA;
106+
#if !BASELINE
107+
csb.CACertificateFile = Path.Combine(AppConfig.CertsPath, "non-ca-client-cert.pem");
108+
#endif
109+
using (var connection = new MySqlConnection(csb.ConnectionString))
110+
{
111+
await Assert.ThrowsAsync(typeof(MySqlException), async () => await connection.OpenAsync());
112+
}
113+
}
114+
115+
readonly DatabaseFixture m_database;
116+
}
117+
118+
}

0 commit comments

Comments
 (0)