diff --git a/cmd/broadcast/main.go b/cmd/broadcast/main.go index f170b54..237ea0b 100644 --- a/cmd/broadcast/main.go +++ b/cmd/broadcast/main.go @@ -19,8 +19,10 @@ import ( ) var ( - debug = flag.Bool("debug", false, "Enable debug logging") - addr = flag.String("addr", ":8080", "Addres to bind to, in the 'ipaddress:port' format") + debug = flag.Bool("debug", false, "Enable debug logging") + addr = flag.String("addr", ":8080", "Address to bind to, in the 'ipaddress:port' format") + tlsCert = flag.String("tls-cert", "", "Path to certificate file for TLS connection") + tlsKey = flag.String("tls-key", "", "Path to key file for TLS connection") ) func main() { @@ -145,7 +147,20 @@ func main() { } }() - go setupHandler(radio, logger, *addr) + handler, err := setupHandler(radio, logger, *addr) + if err != nil { + logger.Err(map[string]any{ + "msg": "Cannot create handler", + "err": err.Error(), + }) + os.Exit(2) + } + + if isValidTLSConf(logger) { + go http.ListenAndServeTLS(*addr, *tlsCert, *tlsKey, handler) + } else { + go http.ListenAndServe(*addr, handler) + } if err := radio.Run(ctx); err != nil { logger.Err(map[string]any{ @@ -168,7 +183,21 @@ func withTimeout[T any](ctx context.Context, respCh <-chan T) (zero T, err error } } -func setupHandler(radio *broadcast.Radio, logger logz.Logger, addr string) error { +func isValidTLSConf(logger logz.Logger) bool { + if *tlsCert == "" && *tlsKey == "" { + return false + } + if (*tlsCert != "" && *tlsKey == "") || (*tlsCert == "" && *tlsKey != "") { + logger.Err(map[string]any{ + "msg": "You must specify both the path to the certificate and to the key to use TLS", + }) + return false + } + + return true +} + +func setupHandler(radio *broadcast.Radio, logger logz.Logger, addr string) (http.Handler, error) { handler := &radioHandler{ radio: radio, logger: logger, @@ -186,7 +215,7 @@ func setupHandler(radio *broadcast.Radio, logger logz.Logger, addr string) error assetsHandler, err := newAssetsHandler(logger) if err != nil { - return err + return nil, err } router := chi.NewRouter() @@ -200,7 +229,7 @@ func setupHandler(radio *broadcast.Radio, logger logz.Logger, addr string) error router.Handle("/liveness", wsHandler) router.Get("/test_ui", testUI.TestUI) - return http.ListenAndServe(addr, router) + return router, nil } func getBaseAddr(addr string) string { diff --git a/devloop/certs/localhost.crt b/devloop/certs/localhost.crt new file mode 100644 index 0000000..e3c810f --- /dev/null +++ b/devloop/certs/localhost.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDyDCCArACEyOJW7h8A9xaVRDy29+WVBLIVw0wDQYJKoZIhvcNAQELBQAwgaAx +CzAJBgNVBAYTAklUMQwwCgYDVQQIDANaQU0xEzARBgNVBAcMCk1pbGFubyBTVUQx +JDAiBgNVBAoMG1pvbmEgQXV0b25vbWEgTWV0cm9wb2xpdGFuYTERMA8GA1UECwwI +VW5pdEBaQU0xEjAQBgNVBAMMCWJyb2FkY2FzdDEhMB8GCSqGSIb3DQEJARYSdW5p +dEBhdXRpc3RpY2kub3JnMB4XDTIzMDMwODIxMzg1MVoXDTI0MDMwNzIxMzg1MVow +gaAxCzAJBgNVBAYTAklUMQwwCgYDVQQIDANaQU0xEzARBgNVBAcMCk1pbGFubyBT +VUQxJDAiBgNVBAoMG1pvbmEgQXV0b25vbWEgTWV0cm9wb2xpdGFuYTERMA8GA1UE +CwwIVW5pdEBaQU0xEjAQBgNVBAMMCWJyb2FkY2FzdDEhMB8GCSqGSIb3DQEJARYS +dW5pdEBhdXRpc3RpY2kub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAwT3qaRiiAonq0bF4dCLqZYCnsFOj4lsCBuM9ZCb2XHAJXu0hcGI95pZbPvMd +X44UIt3y96W0eAZfZFf3CiE/Tm7FPgmbAY6vvoKT9RV3uw7sfJVRYuf5DA7ibjhI +vHKF5ouFFMNlqnR077QI0U0xnfSG6zj6bmLa7i1tfBGxaBncv5AJ1QI8KYaqqgai +wlyDUHjzL9HHpcZMz3Xnhgw3coNHt4hvSACi8pvid8TYY98vQggZtusPpQmmKfhi +yfUV5JpKhk2CRGRsyT/iTxPfGGuNkHT8nxDkadga5znU1+u5YLcG5ip7DsRDcEJk +OzixtVEYpn429dVx9nG/tgvy/wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAmh4tQ +YpikbJhjbDJMN+AcZjE/rcpI70Fet4BRIId/LOxqxN9ICZRPXS6A/mdkHZCtV6H7 +EZLmVZwfeKSt6YMGoyEEnmWRq6QUJKGEOjNvgrEB1ltf/Y8/fYl2S7M1YYvtRPi+ +RychGmBdke0zmIC2oxVXrc40dwKC8jI5eZ2SL+4Kq2rAORqCV8wq2hxRz39SIeUN +JdOZzg7vbmkpPZ80UKcLLhr9WEYJFkQa4ru4jEavYHXhX2SHQQbsY5Sm+zDxQhNB +t7op4WZRIymyqUAFp59DdignN06xgn9Igue+Z8A1TkfymsLD5g/b7629jciaZDRq +3zURMoNFRLvQ2hp1 +-----END CERTIFICATE----- diff --git a/devloop/certs/localhost.csr b/devloop/certs/localhost.csr new file mode 100644 index 0000000..90e4e44 --- /dev/null +++ b/devloop/certs/localhost.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC5jCCAc4CAQAwgaAxCzAJBgNVBAYTAklUMQwwCgYDVQQIDANaQU0xEzARBgNV +BAcMCk1pbGFubyBTVUQxJDAiBgNVBAoMG1pvbmEgQXV0b25vbWEgTWV0cm9wb2xp +dGFuYTERMA8GA1UECwwIVW5pdEBaQU0xEjAQBgNVBAMMCWJyb2FkY2FzdDEhMB8G +CSqGSIb3DQEJARYSdW5pdEBhdXRpc3RpY2kub3JnMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAwT3qaRiiAonq0bF4dCLqZYCnsFOj4lsCBuM9ZCb2XHAJ +Xu0hcGI95pZbPvMdX44UIt3y96W0eAZfZFf3CiE/Tm7FPgmbAY6vvoKT9RV3uw7s +fJVRYuf5DA7ibjhIvHKF5ouFFMNlqnR077QI0U0xnfSG6zj6bmLa7i1tfBGxaBnc +v5AJ1QI8KYaqqgaiwlyDUHjzL9HHpcZMz3Xnhgw3coNHt4hvSACi8pvid8TYY98v +QggZtusPpQmmKfhiyfUV5JpKhk2CRGRsyT/iTxPfGGuNkHT8nxDkadga5znU1+u5 +YLcG5ip7DsRDcEJkOzixtVEYpn429dVx9nG/tgvy/wIDAQABoAAwDQYJKoZIhvcN +AQELBQADggEBAGisqL0G7bvDMEZ8CQ2GfJL5XJCWwNzuLzRfwmp/TBq41u0TPMOb +V0QN/q4ZzrZWhNd0wOwTFsJmZSW7trIp0iQu4NQxF9dy93HffQqAxiK02RwyHtKn ++V4jnCJj3Lumxg1+PJC3P9En/9tNBDGkgLKd9ctXGO6DUTBy8hcdV3ecCwz4ukpO +YsU74aOUkjlnkNpuU+GYG1Lm+FjIQ+Cj3rUHdAn5lZhMPu8z3PzK43Wkcje5XR5c +ytnGi2cAc0dFKeVLwvnnLrYlRjhjUp4niJpnR5I9Cbq+N62/WJgb2Rwrp3yVxUJk +fhrC15IoFGf0YKXbHUXBw+66ywEWq6SnFmQ= +-----END CERTIFICATE REQUEST----- diff --git a/devloop/certs/localhost.key b/devloop/certs/localhost.key new file mode 100644 index 0000000..d8d14d8 --- /dev/null +++ b/devloop/certs/localhost.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBPeppGKICierR +sXh0IuplgKewU6PiWwIG4z1kJvZccAle7SFwYj3mlls+8x1fjhQi3fL3pbR4Bl9k +V/cKIT9ObsU+CZsBjq++gpP1FXe7Dux8lVFi5/kMDuJuOEi8coXmi4UUw2WqdHTv +tAjRTTGd9IbrOPpuYtruLW18EbFoGdy/kAnVAjwphqqqBqLCXINQePMv0celxkzP +deeGDDdyg0e3iG9IAKLym+J3xNhj3y9CCBm26w+lCaYp+GLJ9RXkmkqGTYJEZGzJ +P+JPE98Ya42QdPyfEORp2BrnOdTX67lgtwbmKnsOxENwQmQ7OLG1URimfjb11XH2 +cb+2C/L/AgMBAAECggEACc+6eKaTBzz4argvjPn+27N6ECZXAlWrlyzvf4fI522a +1DKHCZ07VltY+6u9WI4usIyDWxaTQKrWKhKbTOzeOX2/TwSO1bfobWxU1dNGtn0t +/a9ZKAPuLbINxhnee473BHseAS1gmpR6IXeLIRFhzQrO1N+aO4OSaRhuYCfH0aiz +uhFUWDTMSTsaiSKhSiKTak330hlSNkqHJKN68ugAZOj6nZ3N9Fzi81yrYI02s2+Y +HGGBExhCkSDeAc+PV3A+BlCwatdXSXSGb8k3cYemBGNPw/q/QFub1L1JFTqX4HXe +nDsdpFLTyAybZ27GGOvB9103z8I9ID8T8smCFEKKFQKBgQDDin4FZKR8BzbO6vBE +fTN+uGvkypakdyYFYn50I7eXZtvxAETIWFz2u6Btfv6AtZr+GYI2CH8fPo2MHlN3 +oy7Z9axah4RY7XMmXYhmbtdwbkSjFq7DVzpV4GNhzK/XAsIgXnD8Fu41KeDz0erB +/c8bMOpw3XOx02+I8juRQlWFvQKBgQD8/XE7D01dMaFjeq4DHuVF67AcC9JxpZZI +VgfUwOzuwab9lGtEmcrioH0mez+51nsBHVH2QOEi9HkDkR7i/xusQOMIiPqe33o6 +IDGPvpvKBZBEHuAEftGUePukQNbDoKK50FNcmH+yukZUWNF1Gk2N0G/MD9EslXAq +f4qM8hGRawKBgAP5aJ5LcVxj+SUzeTarJMTKksbPp0goc8lgOxm5MB4PpSC81KkN +wrXxEk2naxzKlB/d/NuESLEl4FKcuy2PT4B2kc41OudjzBdXh1ItpotOcm6uI1ct +Cq58JQjz1A8Wq0NlJ/63qJfEBiJufcr7kZ4H3Hv2xEc0+OtboQJOytYxAoGBAJHD +dPoSVwDbF6G5jYk+w9sFcPK33Qid33jOGLT8c4cdDJoOab+c3Mi2r2T8njr02OpL +em3n88+wDAmCE8m2MruMp0LDqaLgIAxdgDDSIfDEQ9r77xan+xkQm+yHbzZH13o4 +Dc/MDcdsjBkNE6HlBcovzjpE4sBNWdMiqTGMR5MBAoGBAMLTVP0nzaLR4JFmRcxO +aKi9FxnC2OYnKSX5JF1LyJc5/DK2mPvOmfN56PyYqn5B+jYmZxv7a3yJxytFp0bn +YlqU1D4sYeRTfgIrfKuNYyMEZV+jTFopZ/oAYK8qVn1+VNWgYswWJCuKTI/76ndC +bKoIzMLy03z1k53O90UOv/8a +-----END PRIVATE KEY-----