Skip to content

chore: minor cleanup PR#315 #322

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class CoderGatewayConnectionProvider : GatewayConnectionProvider {
if (token == null) { // User aborted.
throw IllegalArgumentException("Unable to connect to $deploymentURL, $TOKEN is missing")
}
val client = CoderRestClient(deploymentURL, token.first,null, settings)
val client = CoderRestClient(deploymentURL, token.first, null, settings)
return try {
Pair(client, client.me().username)
} catch (ex: AuthenticationResponseException) {
Expand Down
94 changes: 48 additions & 46 deletions src/main/kotlin/com/coder/gateway/sdk/CoderRestClientService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.util.SystemInfo
import okhttp3.OkHttpClient
Expand All @@ -36,7 +37,6 @@ import java.net.URL
import java.nio.file.Path
import java.security.KeyFactory
import java.security.KeyStore
import java.security.PrivateKey
import java.security.cert.CertificateException
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
Expand All @@ -47,6 +47,7 @@ import java.util.Base64
import java.util.Locale
import java.util.UUID
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.KeyManager
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SNIHostName
import javax.net.ssl.SSLContext
Expand Down Expand Up @@ -251,53 +252,56 @@ class CoderRestClient(
}
}

fun coderSocketFactory(settings: CoderSettingsState) : SSLSocketFactory {
if (settings.tlsCertPath.isBlank() || settings.tlsKeyPath.isBlank()) {
return SSLSocketFactory.getDefault() as SSLSocketFactory
}
fun SSLContextFromPEMs(certPath: String, keyPath: String, caPath: String) : SSLContext {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just refactored this out of coderSocketFactory so we could reuse the pem parsing logic for the SSL context for the tests.

var km: Array<KeyManager>? = null
if (certPath.isNotBlank() && keyPath.isNotBlank()) {
val certificateFactory = CertificateFactory.getInstance("X.509")
val certInputStream = FileInputStream(expandPath(certPath))
val certChain = certificateFactory.generateCertificates(certInputStream)
certInputStream.close()

// ideally we would use something like PemReader from BouncyCastle, but
// BC is used by the IDE. This makes using BC very impractical since
// type casting will mismatch due to the different class loaders.
val privateKeyPem = File(expandPath(keyPath)).readText()
val start: Int = privateKeyPem.indexOf("-----BEGIN PRIVATE KEY-----")
val end: Int = privateKeyPem.indexOf("-----END PRIVATE KEY-----", start)
val pemBytes: ByteArray = Base64.getDecoder().decode(
privateKeyPem.substring(start + "-----BEGIN PRIVATE KEY-----".length, end)
.replace("\\s+".toRegex(), "")
)

val privateKey = try {
val kf = KeyFactory.getInstance("RSA")
val keySpec = PKCS8EncodedKeySpec(pemBytes)
kf.generatePrivate(keySpec)
} catch (e: InvalidKeySpecException) {
val kf = KeyFactory.getInstance("EC")
val keySpec = PKCS8EncodedKeySpec(pemBytes)
kf.generatePrivate(keySpec)
}

val certificateFactory = CertificateFactory.getInstance("X.509")
val certInputStream = FileInputStream(expandPath(settings.tlsCertPath))
val certChain = certificateFactory.generateCertificates(certInputStream)
certInputStream.close()

// ideally we would use something like PemReader from BouncyCastle, but
// BC is used by the IDE. This makes using BC very impractical since
// type casting will mismatch due to the different class loaders.
val privateKeyPem = File(expandPath(settings.tlsKeyPath)).readText()
val start: Int = privateKeyPem.indexOf("-----BEGIN PRIVATE KEY-----")
val end: Int = privateKeyPem.indexOf("-----END PRIVATE KEY-----", start)
val pemBytes: ByteArray = Base64.getDecoder().decode(
privateKeyPem.substring(start + "-----BEGIN PRIVATE KEY-----".length, end)
.replace("\\s+".toRegex(), "")
)

var privateKey : PrivateKey
try {
val kf = KeyFactory.getInstance("RSA")
val keySpec = PKCS8EncodedKeySpec(pemBytes)
privateKey = kf.generatePrivate(keySpec)
} catch (e: InvalidKeySpecException) {
val kf = KeyFactory.getInstance("EC")
val keySpec = PKCS8EncodedKeySpec(pemBytes)
privateKey = kf.generatePrivate(keySpec)
}

val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
keyStore.load(null)
certChain.withIndex().forEach {
keyStore.setCertificateEntry("cert${it.index}", it.value as X509Certificate)
}
keyStore.setKeyEntry("key", privateKey, null, certChain.toTypedArray())
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
keyStore.load(null)
certChain.withIndex().forEach {
keyStore.setCertificateEntry("cert${it.index}", it.value as X509Certificate)
}
keyStore.setKeyEntry("key", privateKey, null, certChain.toTypedArray())

val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
keyManagerFactory.init(keyStore, null)
val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
keyManagerFactory.init(keyStore, null)
km = keyManagerFactory.keyManagers
}

val sslContext = SSLContext.getInstance("TLS")

val trustManagers = coderTrustManagers(settings.tlsCAPath)
sslContext.init(keyManagerFactory.keyManagers, trustManagers, null)
val trustManagers = coderTrustManagers(caPath)
sslContext.init(km, trustManagers, null)
return sslContext
}

fun coderSocketFactory(settings: CoderSettingsState) : SSLSocketFactory {
val sslContext = SSLContextFromPEMs(settings.tlsCertPath, settings.tlsKeyPath, settings.tlsCAPath)
if (settings.tlsAlternateHostname.isBlank()) {
return sslContext.socketFactory
}
Expand Down Expand Up @@ -393,12 +397,11 @@ class AlternateNameSSLSocketFactory(private val delegate: SSLSocketFactory, priv
}

class CoderHostnameVerifier(private val alternateName: String) : HostnameVerifier {
val logger = Logger.getInstance(CoderRestClientService::class.java.simpleName)
override fun verify(host: String, session: SSLSession): Boolean {
if (alternateName.isEmpty()) {
println("using default hostname verifier, alternateName is empty")
return OkHostnameVerifier.verify(host, session)
}
println("Looking for alternate hostname: $alternateName")
val certs = session.peerCertificates ?: return false
for (cert in certs) {
if (cert !is X509Certificate) {
Expand All @@ -411,13 +414,12 @@ class CoderHostnameVerifier(private val alternateName: String) : HostnameVerifie
continue
}
val hostname = entry[1] as String
println("Found cert hostname: $hostname")
logger.debug("Found cert hostname: $hostname")
if (hostname.lowercase(Locale.getDefault()) == alternateName) {
return true
}
}
}
println("No matching hostname found")
return false
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/main/resources/messages/CoderGatewayBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,20 @@ gateway.connector.settings.header-command.comment=An external command that \
outputs additional HTTP headers added to all requests. The command must \
output each header as `key=value` on its own line. The following \
environment variables will be available to the process: CODER_URL.
gateway.connector.settings.tls-cert-path.title=Cert Path:
gateway.connector.settings.tls-cert-path.title=Cert path:
gateway.connector.settings.tls-cert-path.comment=Optionally set this to \
the path of a certificate to use for TLS connections. The certificate \
should be in X.509 PEM format.
gateway.connector.settings.tls-key-path.title=Key Path:
gateway.connector.settings.tls-key-path.title=Key path:
gateway.connector.settings.tls-key-path.comment=Optionally set this to \
the path of the private key that corresponds to the above cert path to use \
for TLS connections. The key should be in X.509 PEM format.
gateway.connector.settings.tls-ca-path.title=CA Path:
gateway.connector.settings.tls-ca-path.title=CA path:
gateway.connector.settings.tls-ca-path.comment=Optionally set this to \
the path of a file containing certificates for an alternate certificate \
authority used to verify TLS certs returned by the Coder service. \
The file should be in X.509 PEM format.
gateway.connector.settings.tls-alt-name.title=Alt Hostname:
gateway.connector.settings.tls-alt-name.title=Alt hostname:
gateway.connector.settings.tls-alt-name.comment=Optionally set this to \
an alternate hostname used for verifying TLS connections. This is useful \
when the hostname used to connect to the Coder service does not match the \
Expand Down
17 changes: 17 additions & 0 deletions src/test/fixtures/tls/chain-intermediate.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvjCCAaagAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJVEVT
VC1yb290MCAXDTIzMTAzMDAyMzY0M1oYDzIxMjMxMDA2MDIzNjQzWjAcMRowGAYD
VQQDDBFURVNULWludGVybWVkaWF0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAMGD9oILmMRcplGkcNdSZMsBR7C2yoPtL9iRp3V2BKpiRZvQuXHSQsdc
S0Tpk6vnIWQTLkCjVRawL9BoOzwK3FZQti9iXRMnHuzl0gQGZGiHJZ2P/efWaVvn
cmH3Cu2oNCVePhgYAMOiipYGQPcjnQ2kUvMLldZ9+WC+EcaD+FA/kaccPX+kOxQg
qQ0MnPQFfno0F8gylOac+ouKOsXya+jlctgK3dxC73/I+Cdq8xrOJ8lXOYxggleB
ZRXNWWUhrzomn4rUP9wNBrQzFCGcqIS+QjlACjlyn0gPU//ZGVRZ8gZXoI8pDYuB
lRyWpt970/ZPFuiyfiasAAAc8gJ3C7cCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zAN
BgkqhkiG9w0BAQsFAAOCAQEAdHRiLqlYAyGNMPj6wzJt3XmwDbU5yEWor4q+GmA9
fupirWXeSqKiqngDfvHlQNKgDlm10Kuk7LDVUcAP27Xnv/uFmHIUF+4g/eIjxvog
RorUD2I9hi0Wyww7E8th/JfnuDX4YbIQrv1r5P4JaCoc0C2NBd1hO1Er2GdNEoXm
UYoZg6/P5YQkWSLYtLPswb/Hf63DvzG94H6HnFBYlumt/5xYLrfD1Lx8099wZVdR
qWXSi/tYi0HJGGUynZCvjdUu5En7eDoyWclGHz3stOUkBlz0efz01bxpiGsE/rRG
Xr6qJt45N0Zktytk5TphoeDAeFB5ZHRRatZsg9CyZGoaIA==
-----END CERTIFICATE-----
27 changes: 27 additions & 0 deletions src/test/fixtures/tls/chain-intermediate.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAwYP2gguYxFymUaRw11JkywFHsLbKg+0v2JGndXYEqmJFm9C5
cdJCx1xLROmTq+chZBMuQKNVFrAv0Gg7PArcVlC2L2JdEyce7OXSBAZkaIclnY/9
59ZpW+dyYfcK7ag0JV4+GBgAw6KKlgZA9yOdDaRS8wuV1n35YL4RxoP4UD+Rpxw9
f6Q7FCCpDQyc9AV+ejQXyDKU5pz6i4o6xfJr6OVy2Ard3ELvf8j4J2rzGs4nyVc5
jGCCV4FlFc1ZZSGvOiafitQ/3A0GtDMUIZyohL5COUAKOXKfSA9T/9kZVFnyBleg
jykNi4GVHJam33vT9k8W6LJ+JqwAABzyAncLtwIDAQABAoIBAQC+gC43rzrgc2S3
km4TSmU3AzeT2x5Z6TDkvd5gX6IQKVXlIgCs8BQVNeJTIK3i2FGits8diqzE/QTU
4QcPAJIP1rzCwM5ngGeNRmEM3U4TKJf7GDkX9ZcahimwDwaPFrre3nu6NEbsUCKl
tdpWcJS3TUDrSkhjMvhAKFxPVLMqKvNK3xg81OmubYDHJ7dmmobJDzklmRlrFCNL
RcQSUYnYruIY4pLmpxVvkFShdxy4oM3f6qanp/nxVvO1of+bqL9fQlgLXSYt83eK
qlUKDdZx/IfckS/DU/8s/PnC5KbrAZB/vNcTIN7USsuAZgP/a8XDLrcH121YZEjW
gIwleYUBAoGBAOtkBKYu+DqlB6xsDJ4XiNji1J19Kmkea+rK5YH21RJlAW3Uh9Y+
tu9J0iQqqQgyIT+v8U0b6uvKjGUoKYbGha7Cl2X93tFL6QGhfewWF/Yqnzr6cBip
IGfHTTWRkZCeNyDII2VEn4B5E+0emCp0p9B8ffr/bUHgFr/wLLD/sDyXAoGBANJ1
XYLK+ilWvL3iV9pcvbuHMP7igXP/wOJsoOpMNixBVhzSm4FZWk4duHdRvMQysk8f
KFiEx+0EJwYyBpbnBCRemhFzergV+6a8tJ4x4rBaVOQBTdLJLPypU5tcLP0iWX+b
oyp7mRT+1ffQ2RcFZBRN6bOvcFrkwdiEl6lglu3hAoGBALnTLpxmrg3V5FXowpk3
aRAXGdPuUMHFg1pKrJ5J1vF7jYI/6rBmuBH1jBCDIQfYU0ksw2ilJnLYZrcg2o+M
P1K0ScL5hKJjs+FWtMrgsi/ie+uac030jiF/Q+OLNIgfbtPRS6gRYX2Rl/p0UZoK
l8RN00KHzJ/ZoPwLRazBXUanAoGBAKzVv9bS1MCwP859HILymMpxyvX3lDJsPb51
UW0462BKw+plt1lxxOzUEZLD6I8Dx1WdE+gmG331ZAr9eFXjII6xtjtQp96YBxO2
c2pbM3x6oq6gt4W8uxpAAK5c84Fq/S8D5OrVmDEa2yNqO25hegAGwD9Ve6LZrKwg
r+Bkt25hAoGAdfY0dHAbZpBSSBixb+XsnDxAne8I4OwTOpExdSH1V1Q85CdTlYLq
FoLuy4rqdrF9kFnasn66diaqUtVaubdG8GyJXTGh1rpOGTjhAjAWCl27fOcO/Ffv
7MqsNI8qhOwIJYaBZ8PXtROp5rf3reqjHu9KqfMj+a2sADiF4bW7KYg=
-----END RSA PRIVATE KEY-----
74 changes: 74 additions & 0 deletions src/test/fixtures/tls/chain-leaf.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=TEST-intermediate
Validity
Not Before: Oct 30 02:36:43 2023 GMT
Not After : Oct 6 02:36:43 2123 GMT
Subject: CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:ca:ff:7b:41:45:d2:46:14:9c:d7:9d:62:79:04:
05:5c:36:c1:43:7d:da:2b:25:26:d1:64:15:42:fa:
10:cc:fd:cf:48:17:87:2f:16:a3:84:11:bd:8a:57:
73:28:24:af:5e:30:a0:57:bb:b9:9d:90:88:41:d3:
c5:6d:20:25:b3:78:6d:1c:96:69:be:ab:52:64:31:
27:4c:d2:d2:02:e5:2e:c2:b0:2c:2e:6f:38:bc:a7:
29:9f:e1:8d:a0:e1:3c:00:9f:37:23:7c:d2:a2:64:
28:fe:97:c1:34:83:1c:29:59:d9:a8:72:c7:bf:22:
02:d0:b5:99:7e:42:7b:56:19:12:21:a9:a4:d8:f0:
70:ef:a1:da:1d:cc:9c:37:7c:45:28:ea:42:f9:20:
1e:6e:87:04:fc:db:0a:80:99:77:0a:38:de:a5:ba:
b0:75:59:3a:cf:76:27:a1:9d:11:08:db:df:05:d1:
0e:22:62:de:61:df:15:b2:77:39:3a:c8:dc:77:e4:
20:c4:20:d7:1a:c0:4b:01:6b:06:4f:4c:b4:23:e9:
dc:18:72:b1:9d:42:14:81:4e:7d:f3:c7:15:72:d5:
b7:81:e7:f8:59:b4:b2:f3:f8:32:c3:aa:8d:d5:d4:
b0:90:bd:da:43:2c:ce:dd:b8:18:83:a2:63:be:66:
99:df
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Subject Alternative Name:
DNS:localhost
Signature Algorithm: sha256WithRSAEncryption
52:1f:1f:e7:4a:e7:37:be:49:a4:54:ed:f2:c7:da:87:f0:b3:
3a:01:21:16:2f:c7:05:2b:c7:dc:2e:98:b1:7e:40:06:32:ca:
cc:d3:95:16:bd:d0:76:a9:9f:d5:cb:64:e0:38:3f:fc:12:62:
08:4b:b1:b0:b9:ce:e0:b5:75:25:d9:83:44:81:db:9c:4d:2f:
39:3b:1c:da:18:fb:99:5b:59:fc:12:de:88:5c:0f:47:58:b3:
5b:70:2f:63:6c:57:19:5b:11:47:2a:98:ba:fe:dd:39:93:34:
9b:c0:7a:3e:4e:6c:ed:e6:ed:e9:9e:92:ab:35:4d:59:57:f8:
44:4f:c4:33:a3:20:ec:09:21:cf:2f:e8:35:61:9b:bf:11:9c:
13:90:81:d4:1c:ec:41:83:86:e3:03:c6:65:c0:db:c8:60:ed:
b1:72:61:66:8f:a9:5e:0f:2d:3d:5c:b6:8a:1f:4e:86:e6:e6:
3d:08:54:c8:41:79:45:3a:92:73:5b:92:34:ba:99:38:f2:9f:
4d:71:37:a1:b7:8d:1b:02:f1:77:d4:3e:6d:23:81:a3:fc:f4:
8b:f2:a6:14:bc:3e:94:2a:7f:bd:d8:fe:41:42:85:31:dd:ed:
b9:03:ad:73:7d:2d:9d:f7:a1:c8:9c:d7:1d:67:83:23:14:da:
61:3c:82:f7
-----BEGIN CERTIFICATE-----
MIIC8jCCAdqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRVEVT
VC1pbnRlcm1lZGlhdGUwIBcNMjMxMDMwMDIzNjQzWhgPMjEyMzEwMDYwMjM2NDNa
MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAMr/e0FF0kYUnNedYnkEBVw2wUN92islJtFkFUL6EMz9z0gXhy8Wo4QR
vYpXcygkr14woFe7uZ2QiEHTxW0gJbN4bRyWab6rUmQxJ0zS0gLlLsKwLC5vOLyn
KZ/hjaDhPACfNyN80qJkKP6XwTSDHClZ2ahyx78iAtC1mX5Ce1YZEiGppNjwcO+h
2h3MnDd8RSjqQvkgHm6HBPzbCoCZdwo43qW6sHVZOs92J6GdEQjb3wXRDiJi3mHf
FbJ3OTrI3HfkIMQg1xrASwFrBk9MtCPp3BhysZ1CFIFOffPHFXLVt4Hn+Fm0svP4
MsOqjdXUsJC92kMszt24GIOiY75mmd8CAwEAAaNEMEIwCwYDVR0PBAQDAgWgMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAUBgNVHREEDTALgglsb2NhbGhv
c3QwDQYJKoZIhvcNAQELBQADggEBAFIfH+dK5ze+SaRU7fLH2ofwszoBIRYvxwUr
x9wumLF+QAYyyszTlRa90Hapn9XLZOA4P/wSYghLsbC5zuC1dSXZg0SB25xNLzk7
HNoY+5lbWfwS3ohcD0dYs1twL2NsVxlbEUcqmLr+3TmTNJvAej5ObO3m7emekqs1
TVlX+ERPxDOjIOwJIc8v6DVhm78RnBOQgdQc7EGDhuMDxmXA28hg7bFyYWaPqV4P
LT1ctoofTobm5j0IVMhBeUU6knNbkjS6mTjyn01xN6G3jRsC8XfUPm0jgaP89Ivy
phS8PpQqf73Y/kFChTHd7bkDrXN9LZ33ocic1x1ngyMU2mE8gvc=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions src/test/fixtures/tls/chain-leaf.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDK/3tBRdJGFJzX
nWJ5BAVcNsFDfdorJSbRZBVC+hDM/c9IF4cvFqOEEb2KV3MoJK9eMKBXu7mdkIhB
08VtICWzeG0clmm+q1JkMSdM0tIC5S7CsCwubzi8pymf4Y2g4TwAnzcjfNKiZCj+
l8E0gxwpWdmocse/IgLQtZl+QntWGRIhqaTY8HDvododzJw3fEUo6kL5IB5uhwT8
2wqAmXcKON6lurB1WTrPdiehnREI298F0Q4iYt5h3xWydzk6yNx35CDEINcawEsB
awZPTLQj6dwYcrGdQhSBTn3zxxVy1beB5/hZtLLz+DLDqo3V1LCQvdpDLM7duBiD
omO+ZpnfAgMBAAECggEBALkDnv+/tkU/Ni/h9sUbIBOKqBxuUPCv3LBNSn+P0M40
qb4oC4KkXIXbcWfsCj3VKaxsH0e3BhaQi0+Lxs2N1i67nJ7IjDpGhUJh9lKzdstC
vJqe3LW5kvmGVY6tkVrGzdw3QJbshkGRjjd0cpf8wycBCDrZ2inewrgcO3hy+Vxe
vhkvUKyB2rjI9xpBGm5YxJiBJGOFZbInp8+Lnx2wuBy+9Dl3/6KzPNc7UKNobwbV
E+kPZoe/zVtsf60mhKQmvyac9eVNXB+U+t/2dnOExG59ROLfR1lsJH5kGdGd/CvR
pLZJwnLX0cTmczz/bcL2iQ/tSClKq2iWEBUUbflIRUECgYEA+P/qOvBQNGXCSMRa
SKEPMUBFbqFMDEsxu0VDZFbRVNmxs5/S5Ta/+aPRzGLtu9oe+Pdhl1xyC1LzSMwm
jJSRrXpnFlLlbahZ8rGV+s52yL/sVy9yR5FDt2B/Y2fVjr0OAJU9aGDjwq92pJ4+
xDhSuIr1SM/DR6YzdBdfiBWkCv8CgYEA0LR8Z5CpBGu4HMfy1wvo6g5TkuqPjkoA
zyCRpEfGa4goJ4ufvldNkni9dZquWFpdCZX0Ips+S6usbc0/BZHj5z40bEQ1Mg+I
WfqzRlKiBIaz9GcJLHORguW4pikT3H9DtzdZmmww4krkHxJDu5TkTLoOBCbDpPj/
eiETduu50SECgYBybQCR5z+kZKL816b5u3IE2xlNNriA6clH2xOWN8No78WW2zqK
dTeRnDPcbhX7/se+98gUS7po88yzRoXskpXDl/1pp9yhIP185xkaMekqZfBRPI+S
zfHFgoXoA56DQuP9ZpfasLPaEtI94i7L82ooPktsE3YVJg59KgSPwAortwKBgQDN
3UpdSdc+Uhbg5OYH82qC/TC42YBTJXIY3ZJrzpTNWxfoshQXR7xvv4N6ruJMqo3d
N7oCLMnNEIDcKjmBAAAjCDvjk4A5ahLgVqdhtX61Ij391Wi6HSEqUfjKhfheZnZg
EkvjQ9cQUDkm4PhI3rw3ZssOk0Imx6oRSPEPO8QloQKBgBeYMhqy3ueJ0bi5o5R0
QcqOYt49wn6bB8fjncBD2eA6ZrLRnBEnyAWoX3d+tIdgZ+0d9fLMQwUYVW2Ql7hh
fPJDcdEx6f2oJYQCSHu9oUXrCFSKdu2CeOGAw6vRknIv71GSDzcNPtiXCWNX4BF+
d13YhhLzFTqfJtaSb1bFSbcu
-----END PRIVATE KEY-----
17 changes: 17 additions & 0 deletions src/test/fixtures/tls/chain-root.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvTCCAaWgAwIBAgIJALEhrLJNS0biMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMMCVRFU1Qtcm9vdDAgFw0yMzEwMzAwMjM2NDNaGA8yMTIzMTAwNjAyMzY0M1ow
FDESMBAGA1UEAwwJVEVTVC1yb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAqLTlMD7rNiC/Hyqz/sh1JBydgNv8CVa/cgCVYQQcGtRl7bs5CfdWti7J
5l7ZEGn+cb+ZyVVyDeF+Tap7zGamQuEkM3C8tettcr7INfKLjNFN94GKtB5LemfK
FFgVA5KWECoovYZPRprgnZuV2QEPdolqwzc3XvaVnmYkxyIhzWD1OFq/vZTFv6eq
fr9JjzWYyv9rCOUmHj/EmVxVVoMYS6Ti3XwOb94Y2CdpuSn3GT4ELN7Tz1B9I0xc
DGKrsjdUIVO5+Bd/5pzQyFMD1UAqsvB9MpHwQswTr/KbrtVC0AQ7fW2q3zOiEg1d
jbNukucc0OwUOIM+UBTtLDBgRzWh5wIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQAQ+7CNlnwdXEx8Q+JAQYw+DOHQEW8BNhi+iurDzgG3
RBdHUO7WZi83ijbWuQkUvsfUsRqTkzg3N9fgY28SAhyhn0UmpGKUN6Eqf2d3nYWl
c5X/vGJrajKZUJdBfCegqCgP2zWJycuG6qAs6dnQOj3GfOlUOakGI3czBlIfOXQv
cU23PbQw0zlXFW6FZIqsuGG4aPeaWhuAJNo2XEDEe8Mdvk9w7pO2hqfBcDe03WyJ
ucxx6vsMUGXBqHiOm8Q5TRjv/Zrd/Bhg8aGQlGDsru/dsjIlcxhrjiZzRQv3KjAj
+lNZcvU6Dsb/4QPJthVfb3ZT6r7QLcOk4TIAVyTVFdYR
-----END CERTIFICATE-----
Loading