From 849d76d6d479eddbe273f8b9f713daa2a6a2eced Mon Sep 17 00:00:00 2001 From: gabrielmer <101006718+gabrielmer@users.noreply.github.com> Date: Mon, 12 Feb 2024 16:28:22 +0200 Subject: [PATCH] chore: automatically generating certs if not provided (Waku Canary) (#2408) --- apps/wakucanary/certsgenerator.nim | 42 ++++++++++++++++++++++++++++++ apps/wakucanary/wakucanary.nim | 25 ++++++++++++++---- 2 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 apps/wakucanary/certsgenerator.nim diff --git a/apps/wakucanary/certsgenerator.nim b/apps/wakucanary/certsgenerator.nim new file mode 100644 index 0000000000..5cf2b5f2e1 --- /dev/null +++ b/apps/wakucanary/certsgenerator.nim @@ -0,0 +1,42 @@ +import + osproc, + os, + httpclient, + strutils + +proc getPublicIP(): string = + let client = newHttpClient() + try: + let response = client.get("http://api.ipify.org") + return response.body + except Exception as e: + echo "Could not fetch public IP: " & e.msg + return "127.0.0.1" + +# Function to generate a self-signed certificate +proc generateSelfSignedCertificate*(certPath: string, keyPath: string) : int = + + # Ensure the OpenSSL is installed + if findExe("openssl") == "": + echo "OpenSSL is not installed or not in the PATH." + return 1 + + let publicIP = getPublicIP() + + if publicIP != "127.0.0.1": + echo "Your public IP address is: ", publicIP + + # Command to generate private key and cert + let + cmd = "openssl req -x509 -newkey rsa:4096 -keyout " & keyPath & " -out " & certPath & + " -sha256 -days 3650 -nodes -subj '/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=" & + publicIP & "'" + res = execCmd(cmd) + + if res == 0: + echo "Successfully generated self-signed certificate and key." + else: + echo "Failed to generate certificate and key." + + return res + \ No newline at end of file diff --git a/apps/wakucanary/wakucanary.nim b/apps/wakucanary/wakucanary.nim index 1789f34a80..6d29a0adc0 100644 --- a/apps/wakucanary/wakucanary.nim +++ b/apps/wakucanary/wakucanary.nim @@ -3,13 +3,15 @@ import confutils, chronos, stew/shims/net, - chronicles/topics_registry + chronicles/topics_registry, + os import libp2p/protocols/ping, libp2p/crypto/[crypto, secp], libp2p/nameresolving/dnsresolver, libp2p/multicodec import + ./certsgenerator, ../../waku/waku_enr, ../../waku/node/peer_manager, ../../waku/waku_core, @@ -24,6 +26,7 @@ const ProtocolsTable = { }.toTable const WebSocketPortOffset = 1000 +const CertsDirectory = "./certs" # cli flags type @@ -154,6 +157,14 @@ proc main(rng: ref HmacDrbgContext): Future[int] {.async.} = nodeTcpPort = Port(conf.nodePort) isWs = peer.addrs[0].contains(multiCodec("ws")).get() isWss = peer.addrs[0].contains(multiCodec("wss")).get() + keyPath = if conf.websocketSecureKeyPath.len > 0: + conf.websocketSecureKeyPath + else: + CertsDirectory & "/key.pem" + certPath = if conf.websocketSecureCertPath.len > 0: + conf.websocketSecureCertPath + else: + CertsDirectory & "/cert.pem" var builder = WakuNodeBuilder.init() builder.withNodeKey(nodeKey) @@ -177,14 +188,18 @@ proc main(rng: ref HmacDrbgContext): Future[int] {.async.} = if isWss and (conf.websocketSecureKeyPath.len == 0 or conf.websocketSecureCertPath.len == 0): - error "WebSocket Secure requires key and certificate, see --help" - return 1 + info "WebSocket Secure requires key and certificate. Generating them" + if not dirExists(CertsDirectory): + createDir(CertsDirectory) + if generateSelfSignedCertificate(certPath, keyPath) != 0: + error "Error generating key and certificate" + return 1 builder.withRecord(record) builder.withNetworkConfiguration(netConfig.tryGet()) builder.withSwitchConfiguration( - secureKey = some(conf.websocketSecureKeyPath), - secureCert = some(conf.websocketSecureCertPath), + secureKey = some(keyPath), + secureCert = some(certPath), nameResolver = resolver, )