From a12c85449a19616c4fbc9864437d9a52fc6586b0 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Fri, 31 Mar 2023 17:01:07 +0300 Subject: [PATCH] WIP --- Cargo.lock | 254 +++++++++++++++++++- Cargo.toml | 1 + proxy/Cargo.toml | 1 + proxy/config/README.md | 0 proxy/config/foo.bar.localhost/server.crt | 77 ++++++ proxy/config/foo.bar.localhost/server.dhall | 5 + proxy/config/foo.bar.localhost/server.key | 28 +++ proxy/config/neon.localhost/server.crt | 77 ++++++ proxy/config/neon.localhost/server.dhall | 5 + proxy/config/neon.localhost/server.key | 28 +++ proxy/config/servers.dhall | 7 + proxy/src/certs.rs | 52 ++++ proxy/src/config.rs | 53 +--- proxy/src/main.rs | 62 +++-- 14 files changed, 578 insertions(+), 72 deletions(-) create mode 100644 proxy/config/README.md create mode 100644 proxy/config/foo.bar.localhost/server.crt create mode 100644 proxy/config/foo.bar.localhost/server.dhall create mode 100644 proxy/config/foo.bar.localhost/server.key create mode 100644 proxy/config/neon.localhost/server.crt create mode 100644 proxy/config/neon.localhost/server.dhall create mode 100644 proxy/config/neon.localhost/server.key create mode 100644 proxy/config/servers.dhall create mode 100644 proxy/src/certs.rs diff --git a/Cargo.lock b/Cargo.lock index 4590e76014..c026b60644 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,37 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "abnf" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33741baa462d86e43fdec5e8ffca7c6ac82847ad06cbfb382c1bdbf527de9e6b" +dependencies = [ + "abnf-core", + "nom", +] + +[[package]] +name = "abnf-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c44e09c43ae1c368fb91a03a566472d0087c26cf7e1b9e8e289c14ede681dd7d" +dependencies = [ + "nom", +] + +[[package]] +name = "abnf_to_pest" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "939d59666dd9a7964a3a5312b9d24c9c107630752ee64f2dd5038189a23fe331" +dependencies = [ + "abnf", + "indexmap", + "itertools", + "pretty", +] + [[package]] name = "addr2line" version = "0.19.0" @@ -63,6 +94,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "annotate-snippets" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36" +dependencies = [ + "unicode-width", +] + [[package]] name = "anyhow" version = "1.0.68" @@ -81,6 +121,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "asn1-rs" version = "0.5.1" @@ -737,7 +783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" dependencies = [ "ciborium-io", - "half", + "half 1.8.2", ] [[package]] @@ -1084,6 +1130,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -1216,6 +1268,42 @@ dependencies = [ "rusticata-macros", ] +[[package]] +name = "dhall" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec26264de25a8e3642fbb37abb24a6c6be9e19795444e6cf1bb88be5c2d55cc7" +dependencies = [ + "abnf_to_pest", + "annotate-snippets", + "elsa", + "half 2.2.1", + "hex", + "home", + "itertools", + "lazy_static", + "minicbor", + "once_cell", + "percent-encoding", + "pest", + "pest_consume", + "pest_generator", + "quote", + "sha2", + "url", +] + +[[package]] +name = "dhall_proc_macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efcdb228bf802b21cd843e5ac3959b6255966238e5ec06d2e4bc6b9935475653" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.10.6" @@ -1238,12 +1326,27 @@ dependencies = [ "syn", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "either" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "elsa" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f74077c3c3aedb99a2683919698285596662518ea13e5eedcf8bdd43b0d0453b" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "encoding_rs" version = "0.8.32" @@ -1581,6 +1684,15 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + [[package]] name = "hash32" version = "0.3.1" @@ -1677,6 +1789,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" +dependencies = [ + "winapi", +] + [[package]] name = "hostname" version = "0.3.1" @@ -2123,6 +2244,27 @@ dependencies = [ "unicase", ] +[[package]] +name = "minicbor" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a20020e8e2d1881d8736f64011bb5ff99f1db9947ce3089706945c8915695cb" +dependencies = [ + "half 1.8.2", + "minicbor-derive", +] + +[[package]] +name = "minicbor-derive" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8608fb1c805b5b6b3d5ab7bd95c40c396df622b64d77b2d621a5eae1eed050ee" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2551,6 +2693,72 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "pest" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_consume" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79447402d15d18e7142e14c72f2e63fa3d155be1bc5b70b3ccbb610ac55f536b" +dependencies = [ + "pest", + "pest_consume_macros", + "pest_derive", +] + +[[package]] +name = "pest_consume_macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8630a7a899cb344ec1c16ba0a6b24240029af34bdc0a21f84e411d7f793f29" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_derive" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "petgraph" version = "0.6.2" @@ -2761,6 +2969,18 @@ dependencies = [ "workspace_hack", ] +[[package]] +name = "pretty" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83f3aa1e3ca87d3b124db7461265ac176b40c277f37e503eaa29c9c75c037846" +dependencies = [ + "arrayvec", + "log", + "typed-arena", + "unicode-segmentation", +] + [[package]] name = "prettyplease" version = "0.1.23" @@ -2939,6 +3159,7 @@ dependencies = [ "rustls-pemfile", "scopeguard", "serde", + "serde_dhall", "serde_json", "sha2", "socket2", @@ -3546,6 +3767,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_dhall" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655a5c686ad80aef90d2e6bfea3715778623c9a659017c8346bc97eb58f9b27d" +dependencies = [ + "dhall", + "dhall_proc_macros", + "doc-comment", + "serde", + "url", +] + [[package]] name = "serde_json" version = "1.0.91" @@ -4433,12 +4667,24 @@ dependencies = [ "utf-8", ] +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + [[package]] name = "uname" version = "0.1.1" @@ -4478,6 +4724,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.10" diff --git a/Cargo.toml b/Cargo.toml index 09cc150606..74cbb7b5da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,6 +87,7 @@ rustls-split = "0.3" scopeguard = "1.1" sentry = { version = "0.29", default-features = false, features = ["backtrace", "contexts", "panic", "rustls", "reqwest" ] } serde = { version = "1.0", features = ["derive"] } +serde_dhall = { version = "0.12.1", default_features = false } serde_json = "1" serde_with = "2.0" sha2 = "0.10.2" diff --git a/proxy/Cargo.toml b/proxy/Cargo.toml index add8b14c95..8b00538131 100644 --- a/proxy/Cargo.toml +++ b/proxy/Cargo.toml @@ -44,6 +44,7 @@ rustls-pemfile.workspace = true rustls.workspace = true scopeguard.workspace = true serde.workspace = true +serde_dhall.workspace = true serde_json.workspace = true sha2.workspace = true socket2.workspace = true diff --git a/proxy/config/README.md b/proxy/config/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/proxy/config/foo.bar.localhost/server.crt b/proxy/config/foo.bar.localhost/server.crt new file mode 100644 index 0000000000..dad374ed02 --- /dev/null +++ b/proxy/config/foo.bar.localhost/server.crt @@ -0,0 +1,77 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 67:2b:fc:80:27:9f:65:dd:42:d7:ef:a8:0a:fe:bd:d1:a8:2d:c8:da + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = *.foo.bar.localhost + Validity + Not Before: Mar 30 12:39:55 2023 GMT + Not After : Sep 3 12:39:55 2202 GMT + Subject: CN = *.foo.bar.localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a3:67:45:c1:97:47:83:a1:1b:34:6a:a5:fa:1a: + 0c:d7:b9:4e:ef:bd:03:8f:64:bf:e3:ca:51:d8:22: + 1e:8b:52:71:09:4e:e3:43:2f:92:45:ea:61:86:06: + fe:49:23:c4:18:a7:ef:4c:81:77:8d:ce:a5:1b:80: + ad:b0:d1:19:71:68:9e:b7:53:6e:d4:9f:d7:ff:d9: + c0:7a:92:8e:04:e9:2b:a4:df:b2:e4:a8:ae:28:da: + c8:5a:f2:d0:b6:98:e3:c4:2d:3a:c7:c3:07:b6:32: + 15:0d:f9:e2:05:77:32:b6:d7:e3:64:b5:8c:c0:83: + 32:25:7d:7f:ad:88:39:25:68:3f:0f:48:4d:60:67: + b9:47:ad:bd:6d:93:73:5c:78:41:d7:db:fa:e9:bf: + 6b:9a:6b:e0:66:c6:90:3c:da:fb:85:2c:45:32:6c: + 0f:18:66:6e:42:f7:0f:93:35:4f:3e:d1:1f:a8:fb: + 18:75:87:19:9a:3a:af:28:28:73:45:9a:87:89:b2: + a6:33:1b:25:83:69:9e:75:8c:06:d6:f3:2a:b2:bc: + 52:64:27:8d:ee:ec:50:88:28:5c:86:6d:8a:92:50: + 00:10:dd:08:42:7c:0d:5a:f8:2b:a2:d6:df:23:0d: + 5f:a8:da:c6:ce:d5:c9:f6:10:a4:de:62:0c:9b:29: + ca:af + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + FE:74:48:82:19:2C:85:19:EB:55:37:8A:70:DF:94:2C:FA:6B:A9:6B + X509v3 Authority Key Identifier: + FE:74:48:82:19:2C:85:19:EB:55:37:8A:70:DF:94:2C:FA:6B:A9:6B + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 08:2b:2a:bc:b7:0f:3e:ec:96:b0:78:87:12:a5:f1:d7:0e:96: + 08:65:34:7d:0a:9b:3d:bd:df:dc:de:3f:5e:0f:57:75:75:a3: + fd:a2:68:29:80:5b:ce:1a:ea:0f:7b:96:ab:ea:92:d0:da:07: + 61:28:32:71:37:d1:3c:6a:ca:e8:f9:9b:80:49:c5:16:40:cc: + 8d:50:8c:4f:4e:6d:73:7b:3a:55:6b:11:76:e3:68:fd:6f:a0: + c8:06:f9:a1:af:28:4d:b9:c5:0d:fd:2c:98:61:7d:22:b6:87: + 43:2b:62:fc:25:9e:fb:f4:09:24:c1:3c:7f:c7:e8:04:b4:c5: + 5a:4b:4e:17:5d:7f:38:f1:d4:35:0c:82:bf:20:46:c7:f4:96: + 8f:12:94:c4:ee:92:e0:5d:09:45:de:a1:40:e5:b4:34:2f:11: + fe:72:5f:81:a5:11:24:a5:04:98:e5:07:59:dc:d8:dc:7b:f6: + 12:ba:8b:d3:cf:dd:de:06:84:23:e7:b3:29:b2:8f:b1:6b:c3: + 71:ee:da:bc:9e:b5:62:a6:68:cb:ea:49:19:34:6c:29:be:ce: + 6d:3b:7a:59:28:59:67:83:e9:6d:37:06:fd:29:f7:ce:fc:fc: + 72:de:23:f5:2b:f6:dc:d2:82:3e:45:bb:e1:ce:14:d7:85:d5: + ec:3b:1c:3c +-----BEGIN CERTIFICATE----- +MIIDHzCCAgegAwIBAgIUZyv8gCefZd1C1++oCv690agtyNowDQYJKoZIhvcNAQEL +BQAwHjEcMBoGA1UEAwwTKi5mb28uYmFyLmxvY2FsaG9zdDAgFw0yMzAzMzAxMjM5 +NTVaGA8yMjAyMDkwMzEyMzk1NVowHjEcMBoGA1UEAwwTKi5mb28uYmFyLmxvY2Fs +aG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKNnRcGXR4OhGzRq +pfoaDNe5Tu+9A49kv+PKUdgiHotScQlO40MvkkXqYYYG/kkjxBin70yBd43OpRuA +rbDRGXFonrdTbtSf1//ZwHqSjgTpK6TfsuSorijayFry0LaY48QtOsfDB7YyFQ35 +4gV3MrbX42S1jMCDMiV9f62IOSVoPw9ITWBnuUetvW2Tc1x4Qdfb+um/a5pr4GbG +kDza+4UsRTJsDxhmbkL3D5M1Tz7RH6j7GHWHGZo6rygoc0Wah4mypjMbJYNpnnWM +BtbzKrK8UmQnje7sUIgoXIZtipJQABDdCEJ8DVr4K6LW3yMNX6jaxs7VyfYQpN5i +DJspyq8CAwEAAaNTMFEwHQYDVR0OBBYEFP50SIIZLIUZ61U3inDflCz6a6lrMB8G +A1UdIwQYMBaAFP50SIIZLIUZ61U3inDflCz6a6lrMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBAAgrKry3Dz7slrB4hxKl8dcOlghlNH0Kmz2939ze +P14PV3V1o/2iaCmAW84a6g97lqvqktDaB2EoMnE30Txqyuj5m4BJxRZAzI1QjE9O +bXN7OlVrEXbjaP1voMgG+aGvKE25xQ39LJhhfSK2h0MrYvwlnvv0CSTBPH/H6AS0 +xVpLThddfzjx1DUMgr8gRsf0lo8SlMTukuBdCUXeoUDltDQvEf5yX4GlESSlBJjl +B1nc2Nx79hK6i9PP3d4GhCPnsymyj7Frw3Hu2ryetWKmaMvqSRk0bCm+zm07elko +WWeD6W03Bv0p9878/HLeI/Ur9tzSgj5Fu+HOFNeF1ew7HDw= +-----END CERTIFICATE----- diff --git a/proxy/config/foo.bar.localhost/server.dhall b/proxy/config/foo.bar.localhost/server.dhall new file mode 100644 index 0000000000..23245cc3a1 --- /dev/null +++ b/proxy/config/foo.bar.localhost/server.dhall @@ -0,0 +1,5 @@ +{ + server_name = "*.foo.bar.localhost", + certificate = ./server.crt as Text, + private_key = ./server.key as Text, +} diff --git a/proxy/config/foo.bar.localhost/server.key b/proxy/config/foo.bar.localhost/server.key new file mode 100644 index 0000000000..b8beaa0bb3 --- /dev/null +++ b/proxy/config/foo.bar.localhost/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCjZ0XBl0eDoRs0 +aqX6GgzXuU7vvQOPZL/jylHYIh6LUnEJTuNDL5JF6mGGBv5JI8QYp+9MgXeNzqUb +gK2w0RlxaJ63U27Un9f/2cB6ko4E6Suk37LkqK4o2sha8tC2mOPELTrHwwe2MhUN ++eIFdzK21+NktYzAgzIlfX+tiDklaD8PSE1gZ7lHrb1tk3NceEHX2/rpv2uaa+Bm +xpA82vuFLEUybA8YZm5C9w+TNU8+0R+o+xh1hxmaOq8oKHNFmoeJsqYzGyWDaZ51 +jAbW8yqyvFJkJ43u7FCIKFyGbYqSUAAQ3QhCfA1a+Cui1t8jDV+o2sbO1cn2EKTe +YgybKcqvAgMBAAECggEACcd9ZwqPzcKxyXiCgSmOYn53kkmjaIzCjKQaV/z+wkNi +6FFY1UoH6oqOX3lLPjoOP92COy6RQjUtMAfT1Cu1L8BLE2uLgt0jjgGVs+lkMKYM +pfwNDXD6pjQBOhjHrxcO7XDL0JJWcVCBAMp76qMb1D+u+poSqg1rcqrNeZVO3s6n +ot4aejb+hDEB8t4ytpDnqULaPvnDmlc5WvVpS8qbGTRiq8DSe5RzEQZp7WHR9Una +0o/rQPu+RiH2+7CesQugg9bc3iaW83DbJjLuODU/4Au/aU/7I0giV8T89UIvtXDl +JzyVDRJNr1qPabZ/H2CFRkfHKovNRpJDEX48VuSR3QKBgQDmr61HA6rRh6zmmehd +V1mroKb9UCR/edBklBSsO2kvWMHPtFEwlszebydcrJa2GwbE37NjKZwkEp1Q/mIk +yX2mjd629j62vzjOejFrW22YOX2LN2cK2Ns9c5T0qnX7ttxy8lw3dE7uU9Y42X8E +Wxm5yIiXImgxIaxCpceR4lzdqwKBgQC1VYUSZcxXIRNjyd98vcD7Ai3zTai4wO3k +WC+Myu2DZr1ZhmY2N0M5b5UUsTL6yOt9fKgqMz3Ww21/zweXx91ts6XmygXIj5ZA +7TyQxPE/PGzG6Olg5o00L//68P9jSBz9HgRWdRtxyJ8NWOUTTGpqA5dKjEj7tia/ +E/QcErSbDQKBgAgNug7wodYO1op2dRZNJmRHh4zwb1XD+vKH+PDKYjG09484zFzV +5vEdEFK788cHyoS1Cp47pafcvoFFYEfIgQp/iXb5wda/dkw/F9qXpovZ9fgWRxKp +332Vu22PRe8zwx6AN5f4B4lqg+AYN8b/JzbFOX+NQ/XzJwBsqTr+nB9hAoGBAIch +McdiAQK07UQhvd+xcEwddayoJKF5dE4DwXuEBbc0Ksq6MxUX3YrBsjD3U+w7KfIb +oR3BjcWrYMArwZbEJCiKBYmU5vZsuiWsJMQlXzomh1E7ZB8H8BYB5xpT2Z1cse2W +Htlm74q9XHmP0zWsbmiOQIIXRJP/S6R89B6vedNJAoGBAJOjRfwepnFpIVXG0waS +S1zavMQZvDsJcvNhedyi34ui5XXi79w+uc13xoFTilhG8DS+tOnw/LsDTP8NeLKv +yENcF/zSHuC4GJJjxoJ+SPlaW+mlofsoCT7zRGRVG27xS6jOwo5/7fYg0aELsq2o +oS/TVaWFJKVtJW64vHdGzMnx +-----END PRIVATE KEY----- diff --git a/proxy/config/neon.localhost/server.crt b/proxy/config/neon.localhost/server.crt new file mode 100644 index 0000000000..fe6c01e314 --- /dev/null +++ b/proxy/config/neon.localhost/server.crt @@ -0,0 +1,77 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 1b:91:d6:a3:a3:1b:c1:47:b3:76:16:a2:43:64:3b:63:61:0d:0c:c8 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = *.neon.localhost + Validity + Not Before: Mar 30 13:19:00 2023 GMT + Not After : Sep 3 13:19:00 2202 GMT + Subject: CN = *.neon.localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:27:17:8b:71:a5:08:65:ec:46:58:69:3d:7d: + b7:91:34:33:3a:50:5c:27:91:34:70:fe:2c:81:fc: + aa:f2:32:60:b3:49:ca:c1:c8:fb:76:73:97:ac:e9: + ff:20:4a:73:48:62:fa:65:d3:81:65:1b:cc:78:00: + 6d:a8:32:8b:ff:61:3c:8b:a2:23:61:de:e3:b4:5f: + cd:ce:7e:ce:05:49:5b:64:81:42:74:81:49:4a:5c: + 3a:f0:d9:40:2d:42:7d:ef:db:b9:d3:54:a5:11:52: + 0b:23:65:fd:c1:5e:58:f7:98:9c:ba:3d:9a:f9:a2: + 50:0c:c4:c8:bf:63:66:aa:e3:29:fe:40:ae:13:8c: + 18:af:20:24:41:63:3e:1d:af:cd:91:32:fa:b9:26: + 96:fb:35:12:1c:62:58:93:33:d2:2c:76:08:f9:c4: + 07:ef:fc:6f:eb:ea:c8:81:5d:d8:73:0a:05:47:79: + 52:b3:24:34:08:c3:b6:a0:aa:af:de:8b:62:f9:6f: + 3a:8f:eb:07:85:ef:2b:de:f7:21:69:7a:63:17:27: + 4a:88:b5:4c:e7:52:73:09:10:c6:ca:eb:f0:c8:31: + cc:d4:59:d6:64:82:ac:ae:96:69:18:5e:19:17:5d: + 9b:86:39:36:a1:9f:90:34:45:73:9b:43:a2:b0:d3: + 8b:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E3:8E:E8:BF:5E:72:36:0A:6D:7F:BE:AF:68:38:A7:CE:71:15:CE:14 + X509v3 Authority Key Identifier: + E3:8E:E8:BF:5E:72:36:0A:6D:7F:BE:AF:68:38:A7:CE:71:15:CE:14 + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 69:23:54:9d:eb:4c:57:f5:cf:8d:5c:d3:f8:2e:65:0b:f1:b8: + 8e:a8:ef:67:dd:89:96:8d:df:f1:9b:36:3a:49:0d:55:dc:07: + eb:c5:e7:c8:73:12:02:6a:02:d3:ca:92:63:f0:61:4b:8a:2a: + 32:c2:23:c2:53:ee:33:6b:eb:9f:e5:f4:df:78:55:bf:d5:86: + 1e:e5:a8:90:e2:df:d7:c2:b8:63:27:a7:2d:ba:43:34:d3:45: + e0:94:53:0a:26:fb:66:ac:c3:96:76:c3:45:a1:ae:d6:30:e0: + b6:c0:a6:d1:8e:51:c7:56:fb:ed:5c:04:a2:66:b9:74:c6:6d: + ef:1e:9e:9a:58:7b:fc:e0:1c:94:fc:17:df:5b:70:e7:cd:f9: + 22:49:3d:59:83:8e:c3:bf:bc:3b:39:68:9e:5a:34:88:1a:61: + f7:53:ac:86:de:76:85:75:f6:b7:86:3f:20:4b:98:63:97:03: + 8b:29:37:32:2c:c1:9a:65:a2:58:17:f2:7b:79:e7:ee:6a:33: + 5b:d0:bd:af:04:dd:02:43:98:a7:e9:0f:35:cb:c0:9d:a6:95: + bf:98:57:4d:cf:b8:a9:bb:de:0c:4d:51:93:df:62:f6:20:bf: + 61:27:7d:2c:be:14:48:5d:d1:75:f9:cb:d9:b3:0a:2b:de:ea: + 2a:4b:9e:c0 +-----BEGIN CERTIFICATE----- +MIIDGTCCAgGgAwIBAgIUG5HWo6MbwUezdhaiQ2Q7Y2ENDMgwDQYJKoZIhvcNAQEL +BQAwGzEZMBcGA1UEAwwQKi5uZW9uLmxvY2FsaG9zdDAgFw0yMzAzMzAxMzE5MDBa +GA8yMjAyMDkwMzEzMTkwMFowGzEZMBcGA1UEAwwQKi5uZW9uLmxvY2FsaG9zdDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKsnF4txpQhl7EZYaT19t5E0 +MzpQXCeRNHD+LIH8qvIyYLNJysHI+3Zzl6zp/yBKc0hi+mXTgWUbzHgAbagyi/9h +PIuiI2He47Rfzc5+zgVJW2SBQnSBSUpcOvDZQC1Cfe/budNUpRFSCyNl/cFeWPeY +nLo9mvmiUAzEyL9jZqrjKf5ArhOMGK8gJEFjPh2vzZEy+rkmlvs1EhxiWJMz0ix2 +CPnEB+/8b+vqyIFd2HMKBUd5UrMkNAjDtqCqr96LYvlvOo/rB4XvK973IWl6Yxcn +Soi1TOdScwkQxsrr8MgxzNRZ1mSCrK6WaRheGRddm4Y5NqGfkDRFc5tDorDTi+EC +AwEAAaNTMFEwHQYDVR0OBBYEFOOO6L9ecjYKbX++r2g4p85xFc4UMB8GA1UdIwQY +MBaAFOOO6L9ecjYKbX++r2g4p85xFc4UMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAGkjVJ3rTFf1z41c0/guZQvxuI6o72fdiZaN3/GbNjpJDVXc +B+vF58hzEgJqAtPKkmPwYUuKKjLCI8JT7jNr65/l9N94Vb/Vhh7lqJDi39fCuGMn +py26QzTTReCUUwom+2asw5Z2w0WhrtYw4LbAptGOUcdW++1cBKJmuXTGbe8enppY +e/zgHJT8F99bcOfN+SJJPVmDjsO/vDs5aJ5aNIgaYfdTrIbedoV19reGPyBLmGOX +A4spNzIswZplolgX8nt55+5qM1vQva8E3QJDmKfpDzXLwJ2mlb+YV03PuKm73gxN +UZPfYvYgv2EnfSy+FEhd0XX5y9mzCive6ipLnsA= +-----END CERTIFICATE----- diff --git a/proxy/config/neon.localhost/server.dhall b/proxy/config/neon.localhost/server.dhall new file mode 100644 index 0000000000..d78f3ff2d0 --- /dev/null +++ b/proxy/config/neon.localhost/server.dhall @@ -0,0 +1,5 @@ +{ + server_name = "*.neon.localhost", + certificate = ./server.crt as Text, + private_key = ./server.key as Text, +} diff --git a/proxy/config/neon.localhost/server.key b/proxy/config/neon.localhost/server.key new file mode 100644 index 0000000000..ba65f04fa6 --- /dev/null +++ b/proxy/config/neon.localhost/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCrJxeLcaUIZexG +WGk9fbeRNDM6UFwnkTRw/iyB/KryMmCzScrByPt2c5es6f8gSnNIYvpl04FlG8x4 +AG2oMov/YTyLoiNh3uO0X83Ofs4FSVtkgUJ0gUlKXDrw2UAtQn3v27nTVKURUgsj +Zf3BXlj3mJy6PZr5olAMxMi/Y2aq4yn+QK4TjBivICRBYz4dr82RMvq5Jpb7NRIc +YliTM9Isdgj5xAfv/G/r6siBXdhzCgVHeVKzJDQIw7agqq/ei2L5bzqP6weF7yve +9yFpemMXJ0qItUznUnMJEMbK6/DIMczUWdZkgqyulmkYXhkXXZuGOTahn5A0RXOb +Q6Kw04vhAgMBAAECggEADrLZw8urwlqL0x1uqa2X9pbGu4BWmb36Wfs03qj7aWId +ieg8IIOz4jVagQAg5/4Hg9+e5OB9jAMPfqgoGA+B6cRzta45XwNhsjD0H4LRC1qE +cyTityy58EfsIUPBzjaX/Yx08LWj7iaJ9wKgVgYAmqr28suto+NmVTe6jIKV46EL +bWmnU0dySOa43ukdhkvQN+FG3hL4iIl+mZ5aTVY8dz885sxYdrKOyrzMREAvHFW6 +m01fWwgbdiMfR2Gu2ZWmvom4+PiE8EES8/Cpct4/E27SFLr3pdB+voIBSh6kotF9 +w0dNqnK1dyIC89gxhcH/PO4rC6uKPM68ZezBsqHZ3QKBgQDMB54bMbcVNK/92nRV +xtM8sk567oAeDwL7VcMq35vmwZU1OcjPg/QswIIZNIx46SXO8a668Wn6OLZYq4dR +FGBWpsMHbQSEdyurYY2bqi5tK5dnKiuCqNmTTtxPA2QgC+PdDcTlJ2FI/RmCeODM +GUcKJd0FyR5BNy8TPM31kFs7zwKBgQDWv6A4cpKzzfY7hf/iOcgmgyipPfXBAdCE +6w6HAEU5JKJDtxIC3roosxOVbrqCMGqPWKCkQvzOr7d9Ok5fYk4WF+qM67xxdzHa +KzmE2+PKDsWBejxjnIMBtDKBkWhOU5/bg/HLDv4RPNwn7f0MjxFpxzYuq3q/dIPN +TcZthbU5TwKBgQCJj1FAEILZ304RH2p0MrtVHvre01K58XEXN7mAfIbGTBpnanBD +yTmlup18lPtowfjlz/j4va+wLvByVCPFvLE/euvfY9c54Icm43zwSQtIO622tq3j +SCh5sx/CfgzRtnKJJbFstuJWrZ63YvxdX2WQJ/se3Xxyh9xLYiGSwSNh7QKBgDFO +/rL3W8f9WrSAKCkBq3tsUkHKAEu45vAeKM/GuB5O0xNJTdFq4sPFmpGNQzXxeAZC +C2CsIPA0WKVgZe5w3A0moKyK1FIZVFEL68Ed3Efg7Gi2cHdO0KXrgk1N3e1eNi5p +NXOylZPPrZ1df+UKVK09GKvOo/iiAEF7wjwTn3DxAoGBAK1iTDV+HrGyxCi2PcoK +yyFCB2QEFw5vvMMMu5lvRjaI9r+igEg1Y8DWhXpUb0hsXnTV192dwhqmB+NYn7Yz +xwlFeKolv+j+5H+IQ4vmEleOlaBLGBH/lAdCcJ0bGcKHHRP+chF6En2tOTk45Gai +4gsDafbyi89fJ/5EoLGRYMe/ +-----END PRIVATE KEY----- diff --git a/proxy/config/servers.dhall b/proxy/config/servers.dhall new file mode 100644 index 0000000000..55b9ce2c85 --- /dev/null +++ b/proxy/config/servers.dhall @@ -0,0 +1,7 @@ +let Server = { server_name : Text, certificate : Text, private_key : Text } + +let servers + : List Server + = [ ./foo.bar.localhost/server.dhall, ./neon.localhost/server.dhall ] + +in servers diff --git a/proxy/src/certs.rs b/proxy/src/certs.rs new file mode 100644 index 0000000000..9d5104c00f --- /dev/null +++ b/proxy/src/certs.rs @@ -0,0 +1,52 @@ +use rustls::{ + server::{ClientHello, ResolvesServerCert}, + sign::CertifiedKey, +}; +use std::sync::Arc; + +pub mod config { + use serde::Deserialize; + use std::path::Path; + + /// TODO: explain. + #[derive(Debug, Default, Clone, Deserialize)] + pub struct TlsServers(Vec); + + impl TlsServers { + pub fn from_config_file(path: impl AsRef) -> anyhow::Result { + let config = serde_dhall::from_file(path).parse()?; + Ok(config) + } + } + + /// This lets us merge multiple configs into one (semigroup). + impl FromIterator for TlsServers { + fn from_iter>(iter: T) -> Self { + Self(iter.into_iter().flat_map(|xs| xs.0).collect()) + } + } + + /// TODO: explain. + #[derive(Debug, Clone, Deserialize)] + pub struct TlsServer { + server_name: Box, + certificate: Box, + private_key: Box, + } +} + +pub struct CertResolver { + resolver: rustls::server::ResolvesServerCertUsingSni, +} + +impl CertResolver { + pub fn new() -> Self { + todo!() + } +} + +impl ResolvesServerCert for CertResolver { + fn resolve(&self, message: ClientHello) -> Option> { + self.resolver.resolve(message) + } +} diff --git a/proxy/src/config.rs b/proxy/src/config.rs index 600db7f8ec..42e04bfe93 100644 --- a/proxy/src/config.rs +++ b/proxy/src/config.rs @@ -1,5 +1,5 @@ use crate::auth; -use anyhow::{bail, ensure, Context}; +use anyhow::{bail, Context}; use std::{str::FromStr, sync::Arc, time::Duration}; pub struct ProxyConfig { @@ -25,57 +25,6 @@ impl TlsConfig { } } -/// Configure TLS for the main endpoint. -pub fn configure_tls(key_path: &str, cert_path: &str) -> anyhow::Result { - let key = { - let key_bytes = std::fs::read(key_path).context("TLS key file")?; - let mut keys = rustls_pemfile::pkcs8_private_keys(&mut &key_bytes[..]) - .context(format!("Failed to read TLS keys at '{key_path}'"))?; - - ensure!(keys.len() == 1, "keys.len() = {} (should be 1)", keys.len()); - keys.pop().map(rustls::PrivateKey).unwrap() - }; - - let cert_chain_bytes = std::fs::read(cert_path) - .context(format!("Failed to read TLS cert file at '{cert_path}.'"))?; - - let cert_chain = { - rustls_pemfile::certs(&mut &cert_chain_bytes[..]) - .context(format!( - "Failed to read TLS certificate chain from bytes from file at '{cert_path}'." - ))? - .into_iter() - .map(rustls::Certificate) - .collect() - }; - - let config = rustls::ServerConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - // allow TLS 1.2 to be compatible with older client libraries - .with_protocol_versions(&[&rustls::version::TLS13, &rustls::version::TLS12])? - .with_no_client_auth() - .with_single_cert(cert_chain, key)? - .into(); - - // determine common name from tls-cert (-c server.crt param). - // used in asserting project name formatting invariant. - let common_name = { - let pem = x509_parser::pem::parse_x509_pem(&cert_chain_bytes) - .context(format!( - "Failed to parse PEM object from bytes from file at '{cert_path}'." - ))? - .1; - let common_name = pem.parse_x509()?.subject().to_string(); - common_name.strip_prefix("CN=*.").map(|s| s.to_string()) - }; - - Ok(TlsConfig { - config, - common_name, - }) -} - /// Helper for cmdline cache options parsing. pub struct CacheOptions { /// Max number of entries. diff --git a/proxy/src/main.rs b/proxy/src/main.rs index 85478da3bc..90e96238f8 100644 --- a/proxy/src/main.rs +++ b/proxy/src/main.rs @@ -7,6 +7,7 @@ mod auth; mod cache; mod cancellation; +mod certs; mod compute; mod config; mod console; @@ -23,10 +24,11 @@ mod url; mod waiters; use anyhow::{bail, Context}; +use auth::BackendType; use clap::{self, Arg}; -use config::ProxyConfig; +use config::{MetricCollectionConfig, ProxyConfig, TlsConfig}; use futures::FutureExt; -use std::{borrow::Cow, future::Future, net::SocketAddr}; +use std::{borrow::Cow, future::Future, net::SocketAddr, path::PathBuf}; use tokio::{net::TcpListener, task::JoinError}; use tracing::{info, warn}; use utils::{project_git_version, sentry_init::init_sentry}; @@ -126,23 +128,31 @@ async fn handle_signals() -> anyhow::Result<()> { } } -/// ProxyConfig is created at proxy startup, and lives forever. -fn build_config(args: &clap::ArgMatches) -> anyhow::Result<&'static ProxyConfig> { - let tls_config = match ( - args.get_one::("tls-key"), - args.get_one::("tls-cert"), - ) { - (Some(key_path), Some(cert_path)) => Some(config::configure_tls(key_path, cert_path)?), - (None, None) => None, +fn build_tls_config(args: &clap::ArgMatches) -> anyhow::Result> { + use certs::config::TlsServers; + + let tls_config = args.get_one::("tls-config"); + let main = tls_config.map(TlsServers::from_config_file).transpose()?; + + let tls_cert = args.get_one::("tls-cert"); + let tls_key = args.get_one::("tls-key"); + + let aux = match (tls_cert, tls_key) { + (Some(key_path), Some(cert_path)) => todo!("implement legacy TLS setup"), + (None, None) => None::<()>, _ => bail!("either both or neither tls-key and tls-cert must be specified"), }; - let metric_collection = match ( - args.get_one::("metric-collection-endpoint"), - args.get_one::("metric-collection-interval"), - ) { + todo!() +} + +fn build_metrics_config(args: &clap::ArgMatches) -> anyhow::Result> { + let endpoint = args.get_one::("metric-collection-endpoint"); + let interval = args.get_one::("metric-collection-interval"); + + let config = match (endpoint, interval) { (Some(endpoint), Some(interval)) => Some(config::MetricCollectionConfig { - endpoint: endpoint.parse()?, + endpoint: endpoint.parse().context("bad metrics endpoint")?, interval: humantime::parse_duration(interval)?, }), (None, None) => None, @@ -152,7 +162,11 @@ fn build_config(args: &clap::ArgMatches) -> anyhow::Result<&'static ProxyConfig> ), }; - let auth_backend = match args.get_one::("auth-backend").unwrap().as_str() { + Ok(config) +} + +fn build_auth_config(args: &clap::ArgMatches) -> anyhow::Result> { + let config = match args.get_one::("auth-backend").unwrap().as_str() { "console" => { let config::CacheOptions { size, ttl } = args .get_one::("wake-compute-cache") @@ -182,10 +196,15 @@ fn build_config(args: &clap::ArgMatches) -> anyhow::Result<&'static ProxyConfig> other => bail!("unsupported auth backend: {other}"), }; + Ok(config) +} + +/// ProxyConfig is created at proxy startup, and lives forever. +fn build_config(args: &clap::ArgMatches) -> anyhow::Result<&'static ProxyConfig> { let config = Box::leak(Box::new(ProxyConfig { - tls_config, - auth_backend, - metric_collection, + tls_config: build_tls_config(args)?, + auth_backend: build_auth_config(args)?, + metric_collection: build_metrics_config(args)?, })); Ok(config) @@ -254,6 +273,11 @@ fn cli() -> clap::Command { .alias("ssl-cert") // backwards compatibility .help("path to TLS cert for client postgres connections"), ) + .arg( + Arg::new("tls-config") + .long("tls-config") + .help("path to the TLS config file"), + ) .arg( Arg::new("metric-collection-endpoint") .long("metric-collection-endpoint")