diff --git a/.ci/certs/ca-chain.crt b/.ci/certs/ca-chain.crt new file mode 100644 index 00000000..f28ea587 --- /dev/null +++ b/.ci/certs/ca-chain.crt @@ -0,0 +1,282 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 6c:5d:e3:ad:35:0d:d0:82:44:26:a8:72:b9:b9:79:e9 + Signature Algorithm: sha256WithRSAEncryption + Issuer: O=example.net, CN=example.net Root Certification Authority + Validity + Not Before: May 27 00:00:00 2020 GMT + Not After : May 29 00:00:00 2030 GMT + Subject: O=example.net, CN=example.net Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:ab:98:8e:31:6d:40:44:aa:f4:68:23:37:3f:de: + b4:6d:bc:7d:12:f3:de:50:92:01:10:fe:02:cd:90: + 24:01:08:47:ef:1b:f6:8e:28:cd:54:d3:0d:5c:12: + 16:ee:d6:60:06:d0:19:b3:35:db:09:3d:82:5f:0a: + 20:9f:f3:cd:c6:cc:53:38:be:24:cf:81:d1:d7:bd: + 23:d3:b6:4d:64:74:17:0e:bd:d7:75:af:78:44:6d: + f6:af:05:62:a0:1a:aa:72:de:9d:4b:2b:0f:8e:b4: + 10:28:52:ca:07:7e:8e:fa:6a:f3:91:87:3d:d4:61: + 4a:2e:ba:fe:f3:d6:74:37:d7:5c:50:45:f4:70:a7: + 71:e6:5b:e0:3a:3a:a1:f8:cf:fe:ea:4b:c5:f6:ff: + 71:88:07:78:79:2b:b0:c7:96:48:02:3b:ee:35:34: + 02:96:f3:7e:e3:61:14:26:00:44:93:53:23:22:5f: + 3d:7d:e4:0c:92:28:8d:ad:74:dd:5f:1a:17:80:32: + 12:62:cf:51:48:54:c5:8a:8f:a4:20:c5:3c:c1:7b: + 11:16:84:11:67:91:2d:b3:01:e7:09:43:6e:06:9f: + ff:3d:56:35:90:f2:ea:c1:12:5f:81:d7:b5:02:62: + 16:33:3c:97:97:3c:74:bd:43:59:35:97:af:30:77: + bd:2f:52:ee:86:eb:a0:ce:0c:a3:1d:63:31:39:5f: + de:8c:cc:a4:f8:59:fe:0b:de:0f:37:6d:1e:e3:ff: + 25:34:64:27:78:15:93:d7:57:a1:cc:16:d2:6c:bf: + 9f:e3:d2:ee:91:2d:56:7b:62:69:d4:51:0d:18:59: + de:79:e7:fb:66:c8:de:8f:fa:ae:d7:64:8a:02:1f: + dd:01:55:c8:95:dd:ae:21:07:f4:c1:89:d6:98:9e: + d8:c7:bf:b3:ae:1b:59:64:ea:a4:72:ce:a0:ed:d8: + 2d:01:b4:58:a9:6b:9c:c7:83:72:20:91:10:87:07: + e9:43:9b:6f:b8:70:1e:25:82:f7:83:dc:52:20:99: + 7e:e8:42:ab:83:65:33:27:1a:a9:0a:99:20:0b:4e: + a9:f9:10:65:b3:9a:4a:e0:4a:38:23:9f:14:85:a2: + 90:ed:9f:9f:fc:5d:70:de:6f:86:b9:6b:f4:00:9c: + ae:2d:9f:f4:49:31:01:0d:83:21:6f:0e:76:68:19: + f1:46:c9:97:3b:9b:57:0c:a3:07:99:a0:b5:54:6b: + b2:b6:a8:9f:2a:76:18:c0:43:f5:9d:fe:12:4a:06: + 39:f2:f9:6f:57:27:31:7f:75:5f:8e:ac:a6:5b:28: + a0:b6:5e:f3:dd:9a:1c:8c:a9:2a:15:61:66:7c:b5: + 3c:41:f1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Name Constraints: critical + Permitted: + DNS:example.net + DNS:example.org + DNS:lan + DNS:onion + email:example.net + email:example.org + + X509v3 Subject Key Identifier: + 8F:9F:67:C9:61:A8:E2:A3:A1:F9:10:D3:EA:B1:6E:9D:0F:B3:E6:99 + X509v3 Subject Alternative Name: + URI:http://ca.example.net/, email:certmaster@example.net + X509v3 Authority Key Identifier: + keyid:8F:9F:67:C9:61:A8:E2:A3:A1:F9:10:D3:EA:B1:6E:9D:0F:B3:E6:99 + + X509v3 Issuer Alternative Name: + URI:http://ca.example.net/, email:certmaster@example.net + Authority Information Access: + CA Issuers - URI:http://ca.example.net/certs/example.net_Root_Certification_Authority.cert.pem + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://ca.example.net/crl/example.net_Root_Certification_Authority.crl + + Signature Algorithm: sha256WithRSAEncryption + 91:07:4a:5e:be:5f:ae:4d:f4:4b:ed:92:4f:94:a3:15:eb:0f: + 32:d7:f6:82:cc:56:18:4c:d7:09:82:7c:bc:28:45:d8:00:7f: + 65:0a:97:f4:ae:ef:a9:6d:d0:a3:dd:5d:0e:10:4e:37:a0:5c: + 73:0d:b0:d1:b0:ff:f4:e0:f3:8c:25:91:26:e1:2c:d5:24:cd: + 48:82:78:cc:96:a8:65:b3:fa:ca:01:c2:43:48:0a:f3:3e:c5: + b5:3b:d3:22:a7:72:0f:87:21:c2:59:c9:c5:74:82:f4:9c:33: + 4e:bb:42:cb:12:09:b1:7d:3d:45:f1:a3:58:46:ec:50:4e:18: + d7:09:5e:92:48:01:f9:e2:89:c9:69:8f:e6:c0:fd:17:43:3f: + 31:fc:a8:7f:f6:f0:8e:1a:60:03:a7:be:d8:f2:3a:f0:f2:38: + 41:c6:33:f1:ab:b0:d5:4f:ad:42:0d:6a:fe:e8:17:9a:52:bb: + c9:fd:ca:5f:f0:72:82:1b:af:b8:a0:6e:a6:2a:ab:37:65:4c: + aa:8f:a2:49:1f:6e:bf:6c:02:93:1c:61:e5:aa:f4:c3:43:c1: + 38:5e:94:57:3d:7c:70:cd:85:c8:d1:26:98:a2:1e:2f:9e:87: + 8c:a4:69:a4:21:e2:2c:dd:3e:91:93:f8:9d:24:72:d7:04:17: + 3a:e1:11:8e:a3:c9:33:46:83:ad:2e:f2:9c:89:da:d0:fc:ee: + 67:19:b0:bc:39:1e:4d:2b:57:74:9b:db:c1:39:99:a2:25:ed: + 7e:fa:bf:54:0d:04:a3:8d:e8:12:3b:87:7f:cc:04:72:e1:ff: + 74:ed:51:1c:c5:98:6d:b7:0c:2b:04:40:c5:16:6a:7e:b0:6b: + 28:e7:05:d8:3c:9c:b0:c5:68:c9:d4:a9:38:cf:24:42:f1:ad: + 9c:e2:52:e2:23:18:2d:3b:44:56:06:e7:1a:c6:f7:57:0f:5c: + 6b:60:e8:2b:fa:98:92:11:da:68:ad:6e:15:b7:f5:03:a8:54: + 9f:0e:09:e4:c1:7d:15:51:03:3b:ad:f5:1b:5d:ac:b2:93:16: + 4a:ac:35:4e:21:96:ec:f3:bb:87:e9:71:fa:b0:42:4e:cb:c4: + 17:84:c7:0e:24:a7:e8:7b:80:e5:f2:78:ac:3d:1d:e7:47:56: + 5e:03:67:5e:80:f8:23:84:0c:fe:ab:1b:0d:a3:01:4a:2c:6f: + 26:17:78:05:00:c9:14:03:b1:0a:87:ef:7f:36:e8:6b:f0:f7: + 9b:0f:93:78:6d:99:05:fb:16:2b:d5:38:aa:b3:9f:32:c9:b2: + ab:af:94:8c:6b:ee:cd:18:f3:d4:43:81:96:0e:c0:00:33:68: + 8d:dd:f2:9d:4c:49:63:a4 +-----BEGIN CERTIFICATE----- +MIIHGTCCBQGgAwIBAgIQbF3jrTUN0IJEJqhyubl56TANBgkqhkiG9w0BAQsFADBJ +MRQwEgYDVQQKDAtleGFtcGxlLm5ldDExMC8GA1UEAwwoZXhhbXBsZS5uZXQgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0yMDA1MjcwMDAwMDBaFw0zMDA1 +MjkwMDAwMDBaMEkxFDASBgNVBAoMC2V4YW1wbGUubmV0MTEwLwYDVQQDDChleGFt +cGxlLm5ldCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAq5iOMW1ARKr0aCM3P960bbx9EvPeUJIBEP4C +zZAkAQhH7xv2jijNVNMNXBIW7tZgBtAZszXbCT2CXwogn/PNxsxTOL4kz4HR170j +07ZNZHQXDr3Xda94RG32rwVioBqqct6dSysPjrQQKFLKB36O+mrzkYc91GFKLrr+ +89Z0N9dcUEX0cKdx5lvgOjqh+M/+6kvF9v9xiAd4eSuwx5ZIAjvuNTQClvN+42EU +JgBEk1MjIl89feQMkiiNrXTdXxoXgDISYs9RSFTFio+kIMU8wXsRFoQRZ5EtswHn +CUNuBp//PVY1kPLqwRJfgde1AmIWMzyXlzx0vUNZNZevMHe9L1LuhuugzgyjHWMx +OV/ejMyk+Fn+C94PN20e4/8lNGQneBWT11ehzBbSbL+f49LukS1We2Jp1FENGFne +eef7Zsjej/qu12SKAh/dAVXIld2uIQf0wYnWmJ7Yx7+zrhtZZOqkcs6g7dgtAbRY +qWucx4NyIJEQhwfpQ5tvuHAeJYL3g9xSIJl+6EKrg2UzJxqpCpkgC06p+RBls5pK +4Eo4I58UhaKQ7Z+f/F1w3m+GuWv0AJyuLZ/0STEBDYMhbw52aBnxRsmXO5tXDKMH +maC1VGuytqifKnYYwEP1nf4SSgY58vlvVycxf3VfjqymWyigtl7z3ZocjKkqFWFm +fLU8QfECAwEAAaOCAfswggH3MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMFoGA1UdHgEB/wRQME6gTDANggtleGFtcGxlLm5ldDANggtleGFtcGxlLm9y +ZzAFggNsYW4wB4IFb25pb24wDYELZXhhbXBsZS5uZXQwDYELZXhhbXBsZS5vcmcw +HQYDVR0OBBYEFI+fZ8lhqOKjofkQ0+qxbp0Ps+aZMDkGA1UdEQQyMDCGFmh0dHA6 +Ly9jYS5leGFtcGxlLm5ldC+BFmNlcnRtYXN0ZXJAZXhhbXBsZS5uZXQwHwYDVR0j +BBgwFoAUj59nyWGo4qOh+RDT6rFunQ+z5pkwOQYDVR0SBDIwMIYWaHR0cDovL2Nh +LmV4YW1wbGUubmV0L4EWY2VydG1hc3RlckBleGFtcGxlLm5ldDBpBggrBgEFBQcB +AQRdMFswWQYIKwYBBQUHMAKGTWh0dHA6Ly9jYS5leGFtcGxlLm5ldC9jZXJ0cy9l +eGFtcGxlLm5ldF9Sb290X0NlcnRpZmljYXRpb25fQXV0aG9yaXR5LmNlcnQucGVt +MFcGA1UdHwRQME4wTKBKoEiGRmh0dHA6Ly9jYS5leGFtcGxlLm5ldC9jcmwvZXhh +bXBsZS5uZXRfUm9vdF9DZXJ0aWZpY2F0aW9uX0F1dGhvcml0eS5jcmwwDQYJKoZI +hvcNAQELBQADggIBAJEHSl6+X65N9Evtkk+UoxXrDzLX9oLMVhhM1wmCfLwoRdgA +f2UKl/Su76lt0KPdXQ4QTjegXHMNsNGw//Tg84wlkSbhLNUkzUiCeMyWqGWz+soB +wkNICvM+xbU70yKncg+HIcJZycV0gvScM067QssSCbF9PUXxo1hG7FBOGNcJXpJI +Afniiclpj+bA/RdDPzH8qH/28I4aYAOnvtjyOvDyOEHGM/GrsNVPrUINav7oF5pS +u8n9yl/wcoIbr7igbqYqqzdlTKqPokkfbr9sApMcYeWq9MNDwThelFc9fHDNhcjR +JpiiHi+eh4ykaaQh4izdPpGT+J0kctcEFzrhEY6jyTNGg60u8pyJ2tD87mcZsLw5 +Hk0rV3Sb28E5maIl7X76v1QNBKON6BI7h3/MBHLh/3TtURzFmG23DCsEQMUWan6w +ayjnBdg8nLDFaMnUqTjPJELxrZziUuIjGC07RFYG5xrG91cPXGtg6Cv6mJIR2mit +bhW39QOoVJ8OCeTBfRVRAzut9RtdrLKTFkqsNU4hluzzu4fpcfqwQk7LxBeExw4k +p+h7gOXyeKw9HedHVl4DZ16A+COEDP6rGw2jAUosbyYXeAUAyRQDsQqH73826Gvw +95sPk3htmQX7FivVOKqznzLJsquvlIxr7s0Y89RDgZYOwAAzaI3d8p1MSWOk +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 22:25:a5:48:fc:37:d9:89:32:b2:89:39:5c:3b:d5:bf + Signature Algorithm: sha256WithRSAEncryption + Issuer: O=example.net, CN=example.net Root Certification Authority + Validity + Not Before: May 27 00:00:00 2020 GMT + Not After : May 28 00:00:00 2030 GMT + Subject: O=example.net, CN=example.net Intermediate Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:d9:bc:a5:da:88:9e:59:88:dc:95:13:c7:2e:8e: + 99:08:a1:14:68:a7:c8:b4:5e:6b:b9:17:19:e1:14: + ce:ad:5a:7c:18:05:da:26:2c:be:6e:91:42:fd:cf: + 6f:40:f0:26:f2:3e:26:29:21:1f:21:9e:c5:ae:b6: + 95:69:13:a8:63:2c:d2:db:61:52:7f:d0:3f:ab:8a: + 14:f7:32:68:f2:5d:a1:d6:d9:da:6b:24:b7:c8:b6: + a5:d6:09:23:63:ad:65:a8:00:4b:76:cd:8b:fd:6d: + d0:63:54:ed:0a:2e:3a:b3:47:f7:c0:8e:1b:b0:82: + 72:74:1e:a6:25:4a:51:7f:55:75:0b:db:87:e8:19: + bd:39:fd:fe:1a:92:e4:16:2d:44:d8:e2:1e:6c:50: + a4:87:cf:61:a2:9e:d9:0d:da:7d:22:dc:06:ff:25: + ca:35:cf:c8:57:b6:e5:97:c5:9d:05:09:81:8b:15: + a1:c9:93:b9:d7:d5:41:2b:fe:e5:bb:ee:78:0d:c7: + 61:eb:d7:5c:99:15:0d:37:3c:9a:77:12:d4:74:d2: + 4b:cc:94:b0:9d:df:83:c1:66:78:6b:bc:e4:f0:de: + 46:ec:2b:bc:a1:d9:34:cb:1e:0d:fc:f1:e6:13:42: + 48:14:f6:af:6a:0f:e5:05:4c:63:0f:c6:a3:98:16: + de:46:4f:5f:ea:d6:1b:ff:af:b5:e6:18:8b:f2:95: + a2:de:25:46:cf:a4:0a:45:eb:59:a8:25:a1:84:6f: + e0:35:0c:4c:d3:ff:20:03:32:ea:19:96:e8:75:f9: + c2:96:f3:2b:e4:53:30:2c:84:35:29:c5:64:d4:ea: + 9e:f0:53:63:32:19:a0:03:ba:76:6d:ab:0c:08:0c: + b6:a9:00:d1:80:9e:3d:33:16:ae:2c:03:d0:29:e3: + af:0d:4a:d0:9f:69:e9:32:ad:d6:e5:90:61:f6:c9: + f6:4e:b7:13:13:ad:d2:02:7a:a5:bb:3a:31:99:a8: + 23:e0:d2:32:24:51:3f:69:5a:57 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + A4:E9:55:7D:E8:F6:BA:A2:6B:71:92:87:C1:98:85:67:AD:BD:09:0E + X509v3 Subject Alternative Name: + URI:http://ca.example.net/, email:certmaster@example.net + X509v3 Authority Key Identifier: + keyid:8F:9F:67:C9:61:A8:E2:A3:A1:F9:10:D3:EA:B1:6E:9D:0F:B3:E6:99 + + X509v3 Issuer Alternative Name: + URI:http://ca.example.net/, email:certmaster@example.net + Authority Information Access: + CA Issuers - URI:http://ca.example.net/certs/example.net_Root_Certification_Authority.cert.pem + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://ca.example.net/crl/example.net_Root_Certification_Authority.crl + + Signature Algorithm: sha256WithRSAEncryption + 91:79:73:e9:0d:e9:0c:b6:ee:a0:79:42:56:11:a6:e0:07:2b: + 9f:d7:19:a8:17:10:54:af:b2:a3:21:3a:1e:53:06:e3:b8:da: + 8e:2c:f0:c8:f6:85:fd:27:d4:f8:ea:d0:13:38:97:4f:80:01: + 4e:7a:36:34:0b:01:52:88:02:3a:d4:fe:e6:90:f0:bd:e2:0f: + 3f:e8:58:36:7f:86:8a:cc:3b:76:ac:5d:dc:18:27:ac:88:f7: + 3b:f8:78:8e:d7:49:d5:65:17:09:69:bc:26:76:63:2f:61:c0: + 91:f7:26:84:44:ef:fc:b1:e2:cd:1f:2e:86:df:21:49:2d:05: + a4:fd:01:43:17:70:fe:0c:f6:10:09:f2:b1:5a:fa:d5:65:8f: + b9:99:5f:81:ca:90:13:ca:20:88:da:c5:6c:49:05:cd:82:78: + 83:29:8d:46:ad:d8:7b:41:de:e0:ed:6f:92:b8:1e:64:77:a9: + bd:d3:f3:b5:82:2a:3e:12:72:d4:02:71:9d:9e:5e:01:2a:2b: + 59:a2:a2:f2:ad:49:bd:b5:fb:7c:4f:52:da:db:c3:c6:09:98: + eb:7b:e7:3f:d6:f0:6a:c0:64:40:df:f0:5a:57:84:d0:bf:20: + 0c:cd:9b:5f:c8:04:98:a6:8e:40:ec:2f:76:8f:1f:58:bf:fe: + 52:7d:9d:2e:d7:1d:14:c7:df:e8:34:7c:ee:7f:06:7c:a5:00: + a9:4b:cb:6b:bb:c7:77:63:01:57:03:fd:9b:90:2b:5a:c2:58: + 3c:77:f8:52:19:a7:94:f5:2c:fe:9b:85:09:94:7c:f9:fb:31: + a6:e6:14:68:12:c0:d1:bc:df:cc:0a:ea:0c:6e:9f:41:22:9b: + 60:64:74:aa:62:95:66:b0:5a:b4:ff:11:cc:92:dc:a3:16:00: + 5a:e3:10:10:a6:34:a3:9b:b0:0a:85:75:9a:b2:da:1f:37:40: + f9:17:10:e4:16:07:a1:ae:69:79:fe:71:43:81:a6:30:89:cd: + 7a:72:9d:a3:b5:a6:bd:be:5f:5a:7c:28:02:13:78:58:67:de: + 78:5f:9d:b4:9d:77:67:17:11:9e:52:1d:a9:ab:70:49:6d:5c: + da:b9:4b:99:e8:d8:1e:e0:06:a6:7a:47:d8:d2:ce:8b:d3:d9: + bf:66:6e:b8:84:4c:3d:5c:e3:fa:92:17:66:44:82:76:2e:ad: + cd:9a:7f:ef:c8:6a:f8:11:6f:9f:cd:63:4e:b7:9a:f7:6c:00: + e7:f1:4e:be:56:1a:d7:26:a4:3c:eb:5b:8a:e1:89:8c:c9:8f: + 81:99:29:9d:d5:fb:c9:1c:df:88:e4:b4:e4:80:03:ed:2a:36: + cf:91:2d:bc:2f:5f:20:f7 +-----BEGIN CERTIFICATE----- +MIIGSDCCBDCgAwIBAgIQIiWlSPw32Ykysok5XDvVvzANBgkqhkiG9w0BAQsFADBJ +MRQwEgYDVQQKDAtleGFtcGxlLm5ldDExMC8GA1UEAwwoZXhhbXBsZS5uZXQgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0yMDA1MjcwMDAwMDBaFw0zMDA1 +MjgwMDAwMDBaMFExFDASBgNVBAoMC2V4YW1wbGUubmV0MTkwNwYDVQQDDDBleGFt +cGxlLm5ldCBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggGi +MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDZvKXaiJ5ZiNyVE8cujpkIoRRo +p8i0Xmu5FxnhFM6tWnwYBdomLL5ukUL9z29A8CbyPiYpIR8hnsWutpVpE6hjLNLb +YVJ/0D+rihT3MmjyXaHW2dprJLfItqXWCSNjrWWoAEt2zYv9bdBjVO0KLjqzR/fA +jhuwgnJ0HqYlSlF/VXUL24foGb05/f4akuQWLUTY4h5sUKSHz2GintkN2n0i3Ab/ +Jco1z8hXtuWXxZ0FCYGLFaHJk7nX1UEr/uW77ngNx2Hr11yZFQ03PJp3EtR00kvM +lLCd34PBZnhrvOTw3kbsK7yh2TTLHg388eYTQkgU9q9qD+UFTGMPxqOYFt5GT1/q +1hv/r7XmGIvylaLeJUbPpApF61moJaGEb+A1DEzT/yADMuoZluh1+cKW8yvkUzAs +hDUpxWTU6p7wU2MyGaADunZtqwwIDLapANGAnj0zFq4sA9Ap468NStCfaekyrdbl +kGH2yfZOtxMTrdICeqW7OjGZqCPg0jIkUT9pWlcCAwEAAaOCAaIwggGeMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSk6VV96Pa6 +omtxkofBmIVnrb0JDjA5BgNVHREEMjAwhhZodHRwOi8vY2EuZXhhbXBsZS5uZXQv +gRZjZXJ0bWFzdGVyQGV4YW1wbGUubmV0MB8GA1UdIwQYMBaAFI+fZ8lhqOKjofkQ +0+qxbp0Ps+aZMDkGA1UdEgQyMDCGFmh0dHA6Ly9jYS5leGFtcGxlLm5ldC+BFmNl +cnRtYXN0ZXJAZXhhbXBsZS5uZXQwaQYIKwYBBQUHAQEEXTBbMFkGCCsGAQUFBzAC +hk1odHRwOi8vY2EuZXhhbXBsZS5uZXQvY2VydHMvZXhhbXBsZS5uZXRfUm9vdF9D +ZXJ0aWZpY2F0aW9uX0F1dGhvcml0eS5jZXJ0LnBlbTBXBgNVHR8EUDBOMEygSqBI +hkZodHRwOi8vY2EuZXhhbXBsZS5uZXQvY3JsL2V4YW1wbGUubmV0X1Jvb3RfQ2Vy +dGlmaWNhdGlvbl9BdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBCwUAA4ICAQCReXPp +DekMtu6geUJWEabgByuf1xmoFxBUr7KjIToeUwbjuNqOLPDI9oX9J9T46tATOJdP +gAFOejY0CwFSiAI61P7mkPC94g8/6Fg2f4aKzDt2rF3cGCesiPc7+HiO10nVZRcJ +abwmdmMvYcCR9yaERO/8seLNHy6G3yFJLQWk/QFDF3D+DPYQCfKxWvrVZY+5mV+B +ypATyiCI2sVsSQXNgniDKY1Grdh7Qd7g7W+SuB5kd6m90/O1gio+EnLUAnGdnl4B +KitZoqLyrUm9tft8T1La28PGCZjre+c/1vBqwGRA3/BaV4TQvyAMzZtfyASYpo5A +7C92jx9Yv/5SfZ0u1x0Ux9/oNHzufwZ8pQCpS8tru8d3YwFXA/2bkCtawlg8d/hS +GaeU9Sz+m4UJlHz5+zGm5hRoEsDRvN/MCuoMbp9BIptgZHSqYpVmsFq0/xHMktyj +FgBa4xAQpjSjm7AKhXWastofN0D5FxDkFgehrml5/nFDgaYwic16cp2jtaa9vl9a +fCgCE3hYZ954X520nXdnFxGeUh2pq3BJbVzauUuZ6Nge4AamekfY0s6L09m/Zm64 +hEw9XOP6khdmRIJ2Lq3Nmn/vyGr4EW+fzWNOt5r3bADn8U6+VhrXJqQ861uK4YmM +yY+BmSmd1fvJHN+I5LTkgAPtKjbPkS28L18g9w== +-----END CERTIFICATE----- diff --git a/elasticsearch/src/cert.rs b/elasticsearch/src/cert.rs index 42e113c9..2bebfff1 100644 --- a/elasticsearch/src/cert.rs +++ b/elasticsearch/src/cert.rs @@ -16,8 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -//! Certificate components -pub use reqwest::Certificate; + +use crate::error::Error; +use std::{ + io::{BufRead, BufReader, Cursor}, + ops::Deref, + vec, +}; /// Validation applied to a SSL/TLS certificate, to establish a HTTPS connection. /// @@ -182,3 +187,88 @@ pub enum CertificateValidation { /// attempting to resolve TLS errors, and **its use on production clusters is strongly discouraged**. None, } + +/// Start marker for PEM encoded certificates. +const BEGIN_CERTIFICATE: &str = "-----BEGIN CERTIFICATE-----"; + +/// End marker for PEM encoded certificates. +const END_CERTIFICATE: &str = "-----END CERTIFICATE-----"; + +/// Represents a server X509 certificate chain. +pub struct Certificate(Vec); + +impl Certificate { + /// Create a `Certificate` chain from PEM encoded certificates. + /// + /// The `pem` input data may contain one or more PEM encoded CA certificates. + /// + /// # Optional + /// This requires the `native-tls`, or `rustls-tls` feature to be enabled. + #[cfg(any(feature = "native-tls", feature = "rustls-tls"))] + pub fn from_pem(pem: &[u8]) -> Result { + let reader = BufReader::new(Cursor::new(pem)); + + // Split the PEM cert into parts without validating the + // contents as this will be done by the + // `reqwest::Certificate::from_pem` call itself. + let mut certs = Vec::new(); + let mut cert = Vec::new(); + let mut begin = false; + for line in reader.lines() { + let line = line?; + match line.as_ref() { + BEGIN_CERTIFICATE if !begin => { + begin = true; + cert.push(line); + } + END_CERTIFICATE if begin => { + begin = false; + cert.push(line); + certs.push(reqwest::Certificate::from_pem(cert.join("\n").as_bytes())?); + cert = Vec::new(); + } + _ if begin => cert.push(line), + _ => {} + } + } + + if certs.is_empty() { + Err(Error::lib( + "could not find PEM certificate in input data".to_string(), + )) + } else { + Ok(Self(certs)) + } + } + + /// Create a `Certificate` from a binary DER encoded certificate. + /// + /// # Optional + /// This requires the `native-tls`, or `rustls-tls` feature to be enabled. + #[cfg(any(feature = "native-tls", feature = "rustls-tls"))] + pub fn from_der(der: &[u8]) -> Result { + Ok(Self(vec![reqwest::Certificate::from_der(der)?])) + } + + /// Append a `Certificate` to the chain. + pub fn append(&mut self, mut cert: Self) { + self.0.append(&mut cert.0); + } +} + +impl IntoIterator for Certificate { + type Item = reqwest::Certificate; + type IntoIter = vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl Deref for Certificate { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/elasticsearch/src/http/transport.rs b/elasticsearch/src/http/transport.rs index 4a8a376b..24c2cd67 100644 --- a/elasticsearch/src/http/transport.rs +++ b/elasticsearch/src/http/transport.rs @@ -216,10 +216,17 @@ impl TransportBuilder { client_builder = match v { CertificateValidation::Default => client_builder, #[cfg(any(feature = "native-tls", feature = "rustls-tls"))] - CertificateValidation::Full(c) => client_builder.add_root_certificate(c), + CertificateValidation::Full(chain) => { + chain.into_iter().fold(client_builder, |client_builder, c| { + client_builder.add_root_certificate(c) + }) + } #[cfg(feature = "native-tls")] - CertificateValidation::Certificate(c) => client_builder - .add_root_certificate(c) + CertificateValidation::Certificate(chain) => chain + .into_iter() + .fold(client_builder, |client_builder, c| { + client_builder.add_root_certificate(c) + }) .danger_accept_invalid_hostnames(true), CertificateValidation::None => client_builder.danger_accept_invalid_certs(true), } diff --git a/elasticsearch/tests/cert.rs b/elasticsearch/tests/cert.rs index 10e84d6c..565d183d 100644 --- a/elasticsearch/tests/cert.rs +++ b/elasticsearch/tests/cert.rs @@ -27,6 +27,7 @@ use os_type::OSType; // TODO: These tests require a cluster configured with Security. Figure out best way to surface this e.g. test category, naming convention, etc. static CA_CERT: &[u8] = include_bytes!("../../.ci/certs/ca.crt"); +static CA_CHAIN_CERT: &[u8] = include_bytes!("../../.ci/certs/ca-chain.crt"); static TESTNODE_SAN_CERT: &[u8] = include_bytes!("../../.ci/certs/testnode_san.crt"); static TESTNODE_CERT: &[u8] = include_bytes!("../../.ci/certs/testnode.crt"); @@ -90,6 +91,20 @@ async fn full_certificate_ca_validation() -> Result<(), failure::Error> { Ok(()) } +/// Try to load a certificate chain. +#[tokio::test] +#[cfg(any(feature = "native-tls", feature = "rustls-tls"))] +async fn full_certificate_ca_chain_validation() -> Result<(), failure::Error> { + let mut cert = Certificate::from_pem(CA_CHAIN_CERT)?; + cert.append(Certificate::from_pem(CA_CERT)?); + assert_eq!(cert.len(), 3, "expected three certificates in CA chain"); + let builder = + client::create_default_builder().cert_validation(CertificateValidation::Full(cert)); + let client = client::create(builder); + let _response = client.ping().send().await?; + Ok(()) +} + /// Certificate provided by the server is the one given to the client and hostname matches #[tokio::test] #[cfg(all(windows, any(feature = "native-tls", feature = "rustls-tls")))]