Skip to content

Commit 74b156e

Browse files
benjirewisBenjamin Rewis
authored andcommitted
GODRIVER-364 Support PKCS8 encrypted client private keys (#565)
1 parent f537927 commit 74b156e

File tree

16 files changed

+607
-70
lines changed

16 files changed

+607
-70
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
-----BEGIN ENCRYPTED PRIVATE KEY-----
2+
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIsqMuOBMVHM4CAggA
3+
MBQGCCqGSIb3DQMHBAjGoriU4YaS6wSCBMhu0dQ8OjzcAJzyhe3osPWFQObhlpsi
4+
sD6Hzx2mcJcZMAv1AG7/MPpPQixiZipQLIiQPOozgjHDqmBp1lGz4FW7sXT01SJT
5+
xlALdUGVrHp5BZRVZGhfZ/SeRknqxoQKqIEZQZeTBJDVZ/dWrLOUfycp0rLWxctq
6+
FVUcb0jq2YL7u9IBIAmFgFyj2ZVWu68HiiwuhKJ0botuFSHe76DP0lthwlHMOR+L
7+
brK7IrMuGhp4xAI16pDoQbwj4AFz2JWhb5WeYhE2CMFhzoZZLgfafBeO/GG04QTt
8+
VB2/Tj5M6jbeCO8H3rYo9yDuWijeOxNDEwRHpLrRcK0T9TouETYzcSFpZIJXhHS3
9+
0ZV44JMGmPP5fkt34mbkBs68nNqcaWuInBx4k7FZZqkd7LyjGRP3mWeqfMhqDaw+
10+
KhAADLRCY7P7ooa3WGGP8+/hdI+I1SR+TCwmiHzY6FRgBlnmlqNH1WS3je4/Dx3w
11+
H8YzPurMpyLlETN1u1DIIZEQteZHVNcZBkTdW1eWOgoOt30wNzrJQPEgPEZgAzvR
12+
4vgKVF68892g755hyOgXl5Hoqf1w2q85l+3qp1zb2UDUvcIkbU7HXnmgZWRJ9T94
13+
kgDlJ82Y+BECQFPVTrEhoVGO0q0eF6On8r7slCoY5edqGdXcyLCuYolEgFHqUFQg
14+
Hjj6x17HQBRa3nnkF3j8tho5kxa6pdvmJcXghJ4Y6Tfs2x9qyjHVYqJH2emuuP9f
15+
Gk5oyicOBTjDnGHG0Hvdd3OSpzQP9P6xMhVByomnz+iGO2CYiJdplKHCeS62Lh7D
16+
px0p7CNxIZtWCBWeQXKqofrJm7PQP+izAqurzGLhMTggCfH8QRZPhiykRnRaIwdV
17+
Ml1veBN6JA91OBkwuioiTH+/zEL8KmpFW5f5okpicUSw6NTx5N2OGqYzqIdo1D0B
18+
0MThRHQszOF4v89O3OPy2PXrYZdxM521CckBsEEVvyKWWd/xlXzheqZvpao2me05
19+
Dmrjb6VTuE5kev/3I6mC6aJMi7CF6fqXaUGm+StlPEAbUudjBnwav8PWTv2hF1VS
20+
Ogj9K6nNG1EyTik4uEltZL6h1EWeZqYap/VJXfwNQn+BAv5xX2mLieIVHpltLQY7
21+
ushULJhMTkMJVQbtHulMyUibE/JBT70ra5GgpjRdpib+3M/7OZOZAm0tWZMovZZS
22+
+UfoC7JApa1FXcsQ03WhGHu3q6kL7TB6VW+QrBnxi8MQBeEydu2cAwrdGKJWtIjL
23+
gBWuAJCEwH/wenim+7YzFYg72aCsaVQxcjYvHAiqEFPDziqk+CLebfZkgF4IEfdF
24+
XbCnAYb8GQmlaJsbEVPtLvVVCYN0/RAEn6ec3ivHkCt4tM67F9pOEaIyk7PWOfpm
25+
ViyUn62O30fQNfWKfjfhD5ttSY/8X0Fa7B9+V4s+2Exb2r0P/wd9k2sjK2IyDNMu
26+
rim0ILriuQ3geBXdJi+uauPA3VnS0uoJoUPs4+nrWHITPOH8ZS7KeZYb9bdEtt61
27+
I47cMXZl9LZASzRnhzgMYN0QBcnnwOXDHKQhwC0FSpB8NZ/gFjgy141/NM1VIIw0
28+
fC9OjnidYxYTv58uFXCPKqCk+iEDQLj68M+VUJgwMSov7M5BA/ymwIPy/548vTZ4
29+
rgE=
30+
-----END ENCRYPTED PRIVATE KEY-----
31+
-----BEGIN CERTIFICATE-----
32+
MIIDdjCCAl6gAwIBAgIDBpgxMA0GCSqGSIb3DQEBBQUAMG4xEzARBgNVBAMTCkNE
33+
cml2ZXIgQ0ExEDAOBgNVBAsTB0RyaXZlcnMxEDAOBgNVBAoTB01vbmdvREIxEjAQ
34+
BgNVBAcTCVJleWtqYXZpazESMBAGA1UECBMJUmV5a2phdmlrMQswCQYDVQQGEwJJ
35+
UzAeFw0xODAyMjgyMDQ0NDhaFw0zODAyMjgyMDQ0NDhaMG0xETAPBgNVBAMTCGV4
36+
dGVybmFsMQ4wDAYDVQQLEwVvdGhlcjEQMA4GA1UEChMHTW9uZ29EQjEWMBQGA1UE
37+
BxMNTmV3IFlvcmsgQ2l0eTERMA8GA1UECBMITmV3IFlvcmsxCzAJBgNVBAYTAlVT
38+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmaii9Oq1jnOjD/NvCOE5
39+
XJAU0xSdWLi28q/HhsrIUwT2aRRObkVPx57Cl90/QKfwYmY4Z1E6oEXQX0F7tcV0
40+
/e9easzBFB69ZS/ztF91xuofeK6tOmAPzRJx4pEAgoY5tlG+Ifs4BS23qe278w51
41+
u1JWo1v50v5qr2MzDt/zZHz1EFz0Q5SBhVe9x5/jyVgd7f6gts2aXFrwE53OavlD
42+
QS3d1aC3xlCGo8tH7UmI0rtJNiwmcPrvbkgSkxmsUDZW4kuvrrY3oDxeLEgaUrZq
43+
rHkVY4WXbbe2359izlpZql5JsaW9FCcqmRP0xmjMZfTcMCLVKCK9JObGj/jlkOzg
44+
QQIDAQABox4wHDAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcN
45+
AQEFBQADggEBAJ2pQoO8zf2BW5jZ8U5WVQlRm/s9LflH7jCkqqIIxRwFENtHEeK0
46+
tOxfW1/JYw6GAuGsLrCXwVI1OeV0KPquoh26sFtrxHeeIxJjAOZ5ov/tLDBciBBD
47+
QCnqPOCehvv/OH9BLFoFdW/3hLqHuKTiiDL9537CiZuDqiKyjucwSlqLk3fBcrna
48+
Se8n2w+g3btD8dEYe0+G+dh2k0EJZ+78LW8Gr642knebxMjrsqD+wooryBBn8jls
49+
9hJjG0D5TbX1koIHDYJE727FC/kWmNhK1Rvt1AKnsMFlrrQBbNK9YvEP6y3KQrb0
50+
R1YgAaV74AIDaGGT1Id+mSteN7KOK34Ruso=
51+
-----END CERTIFICATE-----
52+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZqKL06rWOc6MP
3+
828I4TlckBTTFJ1YuLbyr8eGyshTBPZpFE5uRU/HnsKX3T9Ap/BiZjhnUTqgRdBf
4+
QXu1xXT9715qzMEUHr1lL/O0X3XG6h94rq06YA/NEnHikQCChjm2Ub4h+zgFLbep
5+
7bvzDnW7UlajW/nS/mqvYzMO3/NkfPUQXPRDlIGFV73Hn+PJWB3t/qC2zZpcWvAT
6+
nc5q+UNBLd3VoLfGUIajy0ftSYjSu0k2LCZw+u9uSBKTGaxQNlbiS6+utjegPF4s
7+
SBpStmqseRVjhZdtt7bfn2LOWlmqXkmxpb0UJyqZE/TGaMxl9NwwItUoIr0k5saP
8+
+OWQ7OBBAgMBAAECggEAUm1YHTHa+vOlQWVA5u6KqtDPmvuv/Gv6F+2bhv84vvAm
9+
ju/JsvWTem37zSNuTuzH0sEq+KFmZZuNz8t85WFrBN1nNLtpx7VFvAYhIV0j/PSS
10+
tVZerrXhRAzk8rj+IQaH5vmqmOf+gSipIYraC+Rx226r8y3fsgOwjy0TsqMIGZrp
11+
puczHAaMFvSXzTn2rD7d0AYnTgdIPJNDSwnTvTbnwMNDA4F7E/pJjjkm2kABdXSJ
12+
wTuPnPSeUz0mTYpu4cOc+q+4jhpZr5GaF1declyIl8uU9gyK+gZRdrMHLVsFzdIM
13+
Z+6beF+aCta5wXACou7kRvXQhatiQfTmOe4cpTElwQKBgQDMnkZVhDE7BryVnRE2
14+
N/OJD64g/ygvJOL7rT+dqrNGhJCDHw30Vast2fxmibMk6iI3PkCj3XuTnXEtEOLr
15+
td2bDpWCreMmj0hlFnFAh/p7J6olgbsnJO1Vhn7PcKevUfQVlpcDcu+GcvBHly2r
16+
exAwKNxj6ZxqXf+KtI8w8Ca+PQKBgQDAPnfy7mMg/ytJtSlQz3srWSUERkOI1xcF
17+
GimnVdofKu1PeqAsHOyNTRgoLDmI1NXG+1jva9ML8yBJQAf/+4a8IXKEwCQDVVHs
18+
9iNa7gs6ULo41YRouL8cmat4XLh/OxWwYKZdxQWGTgnHKjVNdf6Df7OOm7uZBbU4
19+
i4sYii/uVQKBgQCCJ39HsDF8gVl9tY4YNdjkayPw+zy9WDJFsrsPeGBWz8X4kc1X
20+
iRK8tLcXJincpk2jZCbL1PthNzmhV+dv1ZwjoFA78o3VnjiHjJH3YUdUBTP2baH1
21+
UUjiKQ4Kt3cCTxf6j3J5kCeKFxx9/UzgkgQHDka6CwQiqK3+tcGLeIa8ZQKBgQCM
22+
wfBvde4s7chTKor6uT/UyGubCptOKTaYrMRM2kZfxb2GESIPyonFF+qVF3R05Gk2
23+
TTib7NXVDQnZuEFjQ1Yuj0rbOhfkPOdEWiAe5uZfp1YCYQuW5ZZAqZ9r/G+18Jv7
24+
zXhideyKnr74DcaDVd6ph6n/w7UC4LQEl9+bcyqPFQKBgATRW/owDjadRVuDB9C4
25+
qzdyXuibMqRRUtvm6k4hs+HyirkrTnWb2YVbRMvrdT783s2wIeKB1oR5aG12A8ln
26+
Hn7CeoLtRU12q65yOkX7vzER6oRmcyBVLhC+izRdoaBmKRuFdmQpXOALZRb/iNzQ
27+
2nUsi2lvjvL42tYvIa8rtm4o
28+
-----END PRIVATE KEY-----
29+
-----BEGIN CERTIFICATE-----
30+
MIIDdjCCAl6gAwIBAgIDBpgxMA0GCSqGSIb3DQEBBQUAMG4xEzARBgNVBAMTCkNE
31+
cml2ZXIgQ0ExEDAOBgNVBAsTB0RyaXZlcnMxEDAOBgNVBAoTB01vbmdvREIxEjAQ
32+
BgNVBAcTCVJleWtqYXZpazESMBAGA1UECBMJUmV5a2phdmlrMQswCQYDVQQGEwJJ
33+
UzAeFw0xODAyMjgyMDQ0NDhaFw0zODAyMjgyMDQ0NDhaMG0xETAPBgNVBAMTCGV4
34+
dGVybmFsMQ4wDAYDVQQLEwVvdGhlcjEQMA4GA1UEChMHTW9uZ29EQjEWMBQGA1UE
35+
BxMNTmV3IFlvcmsgQ2l0eTERMA8GA1UECBMITmV3IFlvcmsxCzAJBgNVBAYTAlVT
36+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmaii9Oq1jnOjD/NvCOE5
37+
XJAU0xSdWLi28q/HhsrIUwT2aRRObkVPx57Cl90/QKfwYmY4Z1E6oEXQX0F7tcV0
38+
/e9easzBFB69ZS/ztF91xuofeK6tOmAPzRJx4pEAgoY5tlG+Ifs4BS23qe278w51
39+
u1JWo1v50v5qr2MzDt/zZHz1EFz0Q5SBhVe9x5/jyVgd7f6gts2aXFrwE53OavlD
40+
QS3d1aC3xlCGo8tH7UmI0rtJNiwmcPrvbkgSkxmsUDZW4kuvrrY3oDxeLEgaUrZq
41+
rHkVY4WXbbe2359izlpZql5JsaW9FCcqmRP0xmjMZfTcMCLVKCK9JObGj/jlkOzg
42+
QQIDAQABox4wHDAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcN
43+
AQEFBQADggEBAJ2pQoO8zf2BW5jZ8U5WVQlRm/s9LflH7jCkqqIIxRwFENtHEeK0
44+
tOxfW1/JYw6GAuGsLrCXwVI1OeV0KPquoh26sFtrxHeeIxJjAOZ5ov/tLDBciBBD
45+
QCnqPOCehvv/OH9BLFoFdW/3hLqHuKTiiDL9537CiZuDqiKyjucwSlqLk3fBcrna
46+
Se8n2w+g3btD8dEYe0+G+dh2k0EJZ+78LW8Gr642knebxMjrsqD+wooryBBn8jls
47+
9hJjG0D5TbX1koIHDYJE727FC/kWmNhK1Rvt1AKnsMFlrrQBbNK9YvEP6y3KQrb0
48+
R1YgAaV74AIDaGGT1Id+mSteN7KOK34Ruso=
49+
-----END CERTIFICATE-----
50+

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ require (
2121
github.com/tidwall/pretty v1.0.0
2222
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c
2323
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc
24-
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5
24+
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d
25+
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
2526
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
2627
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2 // indirect
2728
golang.org/x/text v0.3.3 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,17 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV
103103
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
104104
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo=
105105
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
106+
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
107+
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
108+
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
109+
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
106110
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
107111
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
108112
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
109113
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc=
110114
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
115+
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
116+
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
111117
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
112118
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
113119
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=

mongo/integration/client_test.go

Lines changed: 78 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -81,65 +81,87 @@ func TestClient(t *testing.T) {
8181
assert.Nil(mt, found, "SSLServerHasCertificateAuthority not found in result")
8282
})
8383
mt.RunOpts("x509", mtest.NewOptions().Auth(true).SSL(true), func(mt *mtest.T) {
84-
const user = "C=US,ST=New York,L=New York City,O=MongoDB,OU=other,CN=external"
85-
db := mt.Client.Database("$external")
86-
87-
// We don't care if the user doesn't already exist.
88-
_ = db.RunCommand(
89-
mtest.Background,
90-
bson.D{{"dropUser", user}},
91-
)
92-
err := db.RunCommand(
93-
mtest.Background,
94-
bson.D{
95-
{"createUser", user},
96-
{"roles", bson.A{
97-
bson.D{{"role", "readWrite"}, {"db", "test"}},
98-
}},
84+
testCases := []struct {
85+
certificate string
86+
password string
87+
}{
88+
{
89+
"client.pem",
90+
"",
9991
},
100-
).Err()
101-
assert.Nil(mt, err, "createUser error: %v", err)
102-
103-
baseConnString := mtest.ClusterURI()
104-
// remove username/password from base conn string
105-
revisedConnString := "mongodb://"
106-
split := strings.Split(baseConnString, "@")
107-
assert.Equal(t, 2, len(split), "expected 2 parts after split, got %v (connstring %v)", split, baseConnString)
108-
revisedConnString += split[1]
109-
110-
cs := fmt.Sprintf(
111-
"%s&sslClientCertificateKeyFile=%s&authMechanism=MONGODB-X509&authSource=$external",
112-
revisedConnString,
113-
path.Join(certificatesDir, "client.pem"),
114-
)
115-
authClient, err := mongo.Connect(mtest.Background, options.Client().ApplyURI(cs))
116-
assert.Nil(mt, err, "authClient Connect error: %v", err)
117-
defer func() { _ = authClient.Disconnect(mtest.Background) }()
118-
119-
rdr, err := authClient.Database("test").RunCommand(mtest.Background, bson.D{
120-
{"connectionStatus", 1},
121-
}).DecodeBytes()
122-
assert.Nil(mt, err, "connectionStatus error: %v", err)
123-
users, err := rdr.LookupErr("authInfo", "authenticatedUsers")
124-
assert.Nil(mt, err, "authenticatedUsers not found in response")
125-
elems, err := users.Array().Elements()
126-
assert.Nil(mt, err, "error getting users elements: %v", err)
127-
128-
for _, userElem := range elems {
129-
rdr := userElem.Value().Document()
130-
var u struct {
131-
User string
132-
DB string
133-
}
92+
{
93+
"client-pkcs8-encrypted.pem",
94+
"&sslClientCertificateKeyPassword=password",
95+
},
96+
{
97+
"client-pkcs8-unencrypted.pem",
98+
"",
99+
},
100+
}
101+
for _, tc := range testCases {
102+
mt.Run(tc.certificate, func(mt *mtest.T) {
103+
const user = "C=US,ST=New York,L=New York City,O=MongoDB,OU=other,CN=external"
104+
db := mt.Client.Database("$external")
105+
106+
// We don't care if the user doesn't already exist.
107+
_ = db.RunCommand(
108+
mtest.Background,
109+
bson.D{{"dropUser", user}},
110+
)
111+
err := db.RunCommand(
112+
mtest.Background,
113+
bson.D{
114+
{"createUser", user},
115+
{"roles", bson.A{
116+
bson.D{{"role", "readWrite"}, {"db", "test"}},
117+
}},
118+
},
119+
).Err()
120+
assert.Nil(mt, err, "createUser error: %v", err)
121+
122+
baseConnString := mtest.ClusterURI()
123+
// remove username/password from base conn string
124+
revisedConnString := "mongodb://"
125+
split := strings.Split(baseConnString, "@")
126+
assert.Equal(t, 2, len(split), "expected 2 parts after split, got %v (connstring %v)", split, baseConnString)
127+
revisedConnString += split[1]
128+
129+
cs := fmt.Sprintf(
130+
"%s&sslClientCertificateKeyFile=%s&authMechanism=MONGODB-X509&authSource=$external%s",
131+
revisedConnString,
132+
path.Join(certificatesDir, tc.certificate),
133+
tc.password,
134+
)
135+
authClient, err := mongo.Connect(mtest.Background, options.Client().ApplyURI(cs))
136+
assert.Nil(mt, err, "authClient Connect error: %v", err)
137+
defer func() { _ = authClient.Disconnect(mtest.Background) }()
138+
139+
rdr, err := authClient.Database("test").RunCommand(mtest.Background, bson.D{
140+
{"connectionStatus", 1},
141+
}).DecodeBytes()
142+
assert.Nil(mt, err, "connectionStatus error: %v", err)
143+
users, err := rdr.LookupErr("authInfo", "authenticatedUsers")
144+
assert.Nil(mt, err, "authenticatedUsers not found in response")
145+
elems, err := users.Array().Elements()
146+
assert.Nil(mt, err, "error getting users elements: %v", err)
147+
148+
for _, userElem := range elems {
149+
rdr := userElem.Value().Document()
150+
var u struct {
151+
User string
152+
DB string
153+
}
134154

135-
if err := bson.Unmarshal(rdr, &u); err != nil {
136-
continue
137-
}
138-
if u.User == user && u.DB == "$external" {
139-
return
140-
}
155+
if err := bson.Unmarshal(rdr, &u); err != nil {
156+
continue
157+
}
158+
if u.User == user && u.DB == "$external" {
159+
return
160+
}
161+
}
162+
mt.Fatal("unable to find authenticated user")
163+
})
141164
}
142-
mt.Fatal("unable to find authenticated user")
143165
})
144166
mt.RunOpts("list databases", noClientOpts, func(mt *mtest.T) {
145167
mt.RunOpts("filter", noClientOpts, func(mt *mtest.T) {

mongo/options/clientoptions.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"strings"
2020
"time"
2121

22+
"github.com/youmark/pkcs8"
2223
"go.mongodb.org/mongo-driver/bson/bsoncodec"
2324
"go.mongodb.org/mongo-driver/event"
2425
"go.mongodb.org/mongo-driver/mongo/readconcern"
@@ -885,14 +886,34 @@ func addClientCertFromBytes(cfg *tls.Config, data []byte, keyPasswd string) (str
885886
certDecodedBlock = currentBlock.Bytes
886887
start += len(certBlock)
887888
} else if strings.HasSuffix(currentBlock.Type, "PRIVATE KEY") {
888-
if keyPasswd != "" && x509.IsEncryptedPEMBlock(currentBlock) {
889-
var encoded bytes.Buffer
890-
buf, err := x509.DecryptPEMBlock(currentBlock, []byte(keyPasswd))
891-
if err != nil {
892-
return "", err
889+
isEncrypted := x509.IsEncryptedPEMBlock(currentBlock) || strings.Contains(currentBlock.Type, "ENCRYPTED PRIVATE KEY")
890+
if isEncrypted {
891+
if keyPasswd == "" {
892+
return "", fmt.Errorf("no password provided to decrypt private key")
893893
}
894894

895-
pem.Encode(&encoded, &pem.Block{Type: currentBlock.Type, Bytes: buf})
895+
var keyBytes []byte
896+
var err error
897+
// Process the X.509-encrypted or PKCS-encrypted PEM block.
898+
if x509.IsEncryptedPEMBlock(currentBlock) {
899+
// Only covers encrypted PEM data with a DEK-Info header.
900+
keyBytes, err = x509.DecryptPEMBlock(currentBlock, []byte(keyPasswd))
901+
if err != nil {
902+
return "", err
903+
}
904+
} else if strings.Contains(currentBlock.Type, "ENCRYPTED") {
905+
// The pkcs8 package only handles the PKCS #5 v2.0 scheme.
906+
decrypted, err := pkcs8.ParsePKCS8PrivateKey(currentBlock.Bytes, []byte(keyPasswd))
907+
if err != nil {
908+
return "", err
909+
}
910+
keyBytes, err = x509MarshalPKCS8PrivateKey(decrypted)
911+
if err != nil {
912+
return "", err
913+
}
914+
}
915+
var encoded bytes.Buffer
916+
pem.Encode(&encoded, &pem.Block{Type: currentBlock.Type, Bytes: keyBytes})
896917
keyBlock = encoded.Bytes()
897918
start = len(data) - len(remaining)
898919
} else {

mongo/options/clientoptions_1_10.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ import "crypto/x509"
77
func x509CertSubject(cert *x509.Certificate) string {
88
return cert.Subject.String()
99
}
10+
11+
func x509MarshalPKCS8PrivateKey(pkcs8 interface{}) ([]byte, error) {
12+
return x509.MarshalPKCS8PrivateKey(pkcs8)
13+
}

mongo/options/clientoptions_1_9.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ package options
44

55
import (
66
"crypto/x509"
7+
"fmt"
78
)
89

9-
// We don't support version less then 1.10, but Evergreen needs to be able to compile the driver
10-
// using version 1.8.
10+
// We don't support Go versions less than 1.10, but Evergreen needs to be able to compile the driver
11+
// using version 1.9 and cert.Subject
1112
func x509CertSubject(cert *x509.Certificate) string {
1213
return ""
1314
}
15+
16+
// We don't support Go versions less than 1.10, but Evergreen needs to be able to compile the driver
17+
// using version 1.9 and x509.MarshalPKCS8PrivateKey()
18+
func x509MarshalPKCS8PrivateKey(pkcs8 interface{}) ([]byte, error) {
19+
return nil, fmt.Errorf("PKCS8-encrypted client private keys are only supported with go1.10+")
20+
}

vendor/github.com/youmark/pkcs8/.gitignore

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/youmark/pkcs8/.travis.yml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)