Cosmos-Server/src/httpServer.go

282 lines
8.8 KiB
Go
Raw Normal View History

2023-02-26 22:26:09 +00:00
package main
import (
"net/http"
2023-03-25 20:15:00 +00:00
"github.com/azukaar/cosmos-server/src/utils"
"github.com/azukaar/cosmos-server/src/user"
"github.com/azukaar/cosmos-server/src/configapi"
"github.com/azukaar/cosmos-server/src/proxy"
"github.com/azukaar/cosmos-server/src/docker"
2023-02-26 22:26:09 +00:00
"github.com/gorilla/mux"
2023-03-10 20:59:56 +00:00
"strconv"
"time"
2023-03-12 18:17:28 +00:00
"os"
"strings"
2023-03-10 20:59:56 +00:00
"github.com/go-chi/chi/middleware"
"github.com/go-chi/httprate"
"crypto/tls"
2023-03-12 18:17:28 +00:00
spa "github.com/roberthodgen/spa-server"
"github.com/foomo/simplecert"
"github.com/foomo/tlsconfig"
2023-02-26 22:26:09 +00:00
)
2023-03-10 20:59:56 +00:00
var serverPortHTTP = ""
var serverPortHTTPS = ""
2023-02-26 22:26:09 +00:00
func startHTTPServer(router *mux.Router) {
2023-03-10 20:59:56 +00:00
utils.Log("Listening to HTTP on :" + serverPortHTTP)
2023-02-26 22:26:09 +00:00
err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, router)
if err != nil {
2023-03-10 20:59:56 +00:00
utils.Fatal("Listening to HTTP", err)
2023-02-26 22:26:09 +00:00
}
}
func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
config := utils.GetMainConfig()
serverHostname := "0.0.0.0"
cfg := simplecert.Default
cfg.Domains = utils.GetAllHostnames()
cfg.CacheDir = "/config/certificates"
cfg.SSLEmail = config.HTTPConfig.SSLEmail
cfg.HTTPAddress = serverHostname+":"+serverPortHTTP
cfg.TLSAddress = serverHostname+":"+serverPortHTTPS
if config.HTTPConfig.DNSChallengeProvider != "" {
cfg.DNSProvider = config.HTTPConfig.DNSChallengeProvider
}
2023-03-29 20:38:50 +00:00
cfg.FailedToRenewCertificate = func(err error) {
utils.Error("Failed to renew certificate", err)
}
var certReloader *simplecert.CertReloader
var errSimCert error
if(config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
certReloader, errSimCert = simplecert.Init(cfg, nil)
if errSimCert != nil {
// Temporary before we have a better way to handle this
utils.Error("simplecert init failed, HTTPS wont renew", errSimCert)
startHTTPServer(router)
return
}
}
2023-03-25 20:15:00 +00:00
// redirect http to https
go (func () {
// err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, http.HandlerFunc(simplecert.Redirect))
err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// change port in host
if strings.HasSuffix(r.Host, ":" + serverPortHTTP) {
if serverPortHTTPS != "443" {
r.Host = r.Host[:len(r.Host)-len(":" + serverPortHTTP)] + ":" + serverPortHTTPS
} else {
r.Host = r.Host[:len(r.Host)-len(":" + serverPortHTTP)]
2023-02-26 22:26:09 +00:00
}
}
http.Redirect(w, r, "https://"+r.Host+r.URL.String(), http.StatusMovedPermanently)
}))
if err != nil {
utils.Fatal("Listening to HTTP (Redirecting to HTTPS)", err)
}
})()
2023-02-26 22:26:09 +00:00
utils.Log("Listening to HTTP on :" + serverPortHTTP)
utils.Log("Listening to HTTPS on :" + serverPortHTTPS)
utils.IsHTTPS = true
2023-03-10 20:59:56 +00:00
tlsConf := tlsconfig.NewServerTLSConfig(tlsconfig.TLSModeServerStrict)
2023-03-10 20:59:56 +00:00
if(config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
tlsConf.GetCertificate = certReloader.GetCertificateFunc()
} else {
2023-03-10 20:59:56 +00:00
cert, errCert := tls.X509KeyPair(([]byte)(tlsCert), ([]byte)(tlsKey))
if errCert != nil {
utils.Fatal("Getting Certificate pair", errCert)
}
tlsConf.Certificates = []tls.Certificate{cert}
}
server := http.Server{
TLSConfig: tlsConf,
Addr: serverHostname + ":" + serverPortHTTPS,
ReadTimeout: 0,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 0,
IdleTimeout: 30 * time.Second,
Handler: router,
DisableGeneralOptionsHandler: true,
}
2023-02-26 22:26:09 +00:00
// start https server
errServ := server.ListenAndServeTLS("", "")
2023-02-26 22:26:09 +00:00
if errServ != nil {
utils.Fatal("Listening to HTTPS", errServ)
}
2023-02-26 22:26:09 +00:00
}
2023-03-10 20:59:56 +00:00
func tokenMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//Header.Del
r.Header.Del("x-cosmos-user")
r.Header.Del("x-cosmos-role")
r.Header.Del("x-cosmos-mfa")
2023-03-10 20:59:56 +00:00
u, err := user.RefreshUserToken(w, r)
if err != nil {
return
}
r.Header.Set("x-cosmos-user", u.Nickname)
r.Header.Set("x-cosmos-role", strconv.Itoa((int)(u.Role)))
r.Header.Set("x-cosmos-mfa", strconv.Itoa((int)(u.MFAState)))
2023-03-10 20:59:56 +00:00
next.ServeHTTP(w, r)
})
}
func StartServer() {
baseMainConfig := utils.GetBaseMainConfig()
config := utils.GetMainConfig()
HTTPConfig := config.HTTPConfig
serverPortHTTP = HTTPConfig.HTTPPort
serverPortHTTPS = HTTPConfig.HTTPSPort
2023-05-05 18:06:59 +00:00
// serverHostname := HTTPConfig.Hostname
var tlsCert = HTTPConfig.TLSCert
var tlsKey= HTTPConfig.TLSKey
2023-02-26 22:26:09 +00:00
domains := utils.GetAllHostnames()
oldDomains := baseMainConfig.HTTPConfig.TLSKeyHostsCached
NeedsRefresh := (tlsCert == "" || tlsKey == "") || !utils.StringArrayEquals(domains, oldDomains)
if(NeedsRefresh && HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"]) {
2023-03-10 20:59:56 +00:00
utils.Log("Generating new TLS certificate")
pub, priv := utils.GenerateRSAWebCertificates(domains)
2023-03-10 20:59:56 +00:00
baseMainConfig.HTTPConfig.TLSCert = pub
baseMainConfig.HTTPConfig.TLSKey = priv
baseMainConfig.HTTPConfig.TLSKeyHostsCached = domains
2023-03-10 20:59:56 +00:00
utils.SetBaseMainConfig(baseMainConfig)
utils.Log("Saved new TLS certificate")
tlsCert = pub
tlsKey = priv
2023-02-26 22:26:09 +00:00
}
if ((HTTPConfig.AuthPublicKey == "" || HTTPConfig.AuthPrivateKey == "") && HTTPConfig.GenerateMissingAuthCert) {
2023-03-10 20:59:56 +00:00
utils.Log("Generating new Auth ED25519 certificate")
pub, priv := utils.GenerateEd25519Certificates()
baseMainConfig.HTTPConfig.AuthPublicKey = pub
baseMainConfig.HTTPConfig.AuthPrivateKey = priv
utils.SetBaseMainConfig(baseMainConfig)
utils.Log("Saved new Auth ED25519 certificate")
2023-02-26 22:26:09 +00:00
}
2023-03-12 18:17:28 +00:00
router := mux.NewRouter().StrictSlash(true)
2023-05-01 10:00:45 +00:00
router.HandleFunc("/logo", SendLogo)
2023-02-26 22:26:09 +00:00
// need rewrite bc it catches too many things and prevent
// client to be notified of the error
// router.Use(middleware.Recoverer)
2023-03-10 20:59:56 +00:00
router.Use(middleware.Logger)
router.Use(utils.SetSecurityHeaders)
if config.BlockedCountries != nil && len(config.BlockedCountries) > 0 {
router.Use(utils.BlockByCountryMiddleware(config.BlockedCountries))
}
2023-03-12 18:17:28 +00:00
srapi := router.PathPrefix("/cosmos").Subrouter()
2023-03-10 20:59:56 +00:00
2023-03-29 20:38:50 +00:00
srapi.HandleFunc("/api/status", StatusRoute)
2023-05-01 10:00:45 +00:00
srapi.HandleFunc("/api/can-send-email", CanSendEmail)
2023-04-27 18:29:26 +00:00
srapi.HandleFunc("/api/favicon", GetFavicon)
srapi.HandleFunc("/api/ping", PingURL)
2023-03-29 20:38:50 +00:00
srapi.HandleFunc("/api/newInstall", NewInstallRoute)
2023-03-12 18:17:28 +00:00
srapi.HandleFunc("/api/login", user.UserLogin)
srapi.HandleFunc("/api/logout", user.UserLogout)
srapi.HandleFunc("/api/register", user.UserRegister)
srapi.HandleFunc("/api/invite", user.UserResendInviteLink)
srapi.HandleFunc("/api/me", user.Me)
srapi.HandleFunc("/api/mfa", user.API2FA)
srapi.HandleFunc("/api/password-reset", user.ResetPassword)
2023-03-16 18:56:36 +00:00
srapi.HandleFunc("/api/config", configapi.ConfigRoute)
srapi.HandleFunc("/api/restart", configapi.ConfigApiRestart)
2023-03-10 20:59:56 +00:00
2023-03-12 18:17:28 +00:00
srapi.HandleFunc("/api/users/{nickname}", user.UsersIdRoute)
srapi.HandleFunc("/api/users", user.UsersRoute)
2023-03-25 20:15:00 +00:00
2023-05-05 18:05:33 +00:00
srapi.HandleFunc("/api/servapps/{containerId}/manage/{action}", docker.ManageContainerRoute)
2023-03-31 19:19:38 +00:00
srapi.HandleFunc("/api/servapps/{containerId}/secure/{status}", docker.SecureContainerRoute)
2023-03-25 20:15:00 +00:00
srapi.HandleFunc("/api/servapps", docker.ContainersRoute)
2023-03-10 20:59:56 +00:00
2023-05-05 18:05:33 +00:00
// if(!config.HTTPConfig.AcceptAllInsecureHostname) {
// srapi.Use(utils.EnsureHostname(serverHostname))
// }
2023-03-18 19:59:32 +00:00
srapi.Use(tokenMiddleware)
2023-04-28 18:28:01 +00:00
srapi.Use(proxy.SmartShieldMiddleware(
utils.SmartShieldPolicy{
Enabled: true,
PolicyStrictness: 1,
PerUserRequestLimit: 5000,
2023-04-28 18:28:01 +00:00
},
))
2023-03-13 00:49:27 +00:00
srapi.Use(utils.MiddlewareTimeout(20 * time.Second))
2023-04-30 20:36:51 +00:00
srapi.Use(utils.BlockPostWithoutReferer)
srapi.Use(proxy.BotDetectionMiddleware)
2023-03-13 00:49:27 +00:00
srapi.Use(httprate.Limit(60, 1*time.Minute,
2023-03-10 20:59:56 +00:00
httprate.WithKeyFuncs(httprate.KeyByIP),
httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) {
utils.Error("Too many requests. Throttling", nil)
utils.HTTPError(w, "Too many requests",
http.StatusTooManyRequests, "HTTP003")
return
}),
))
2023-03-12 18:17:28 +00:00
pwd,_ := os.Getwd()
utils.Log("Starting in " + pwd)
if _, err := os.Stat(pwd + "/static"); os.IsNotExist(err) {
utils.Fatal("Static folder not found at " + pwd + "/static", err)
}
2023-03-16 18:56:36 +00:00
2023-05-05 18:05:33 +00:00
2023-03-12 18:17:28 +00:00
fs := spa.SpaHandler(pwd + "/static", "index.html")
2023-05-05 18:05:33 +00:00
// if(!config.HTTPConfig.AcceptAllInsecureHostname) {
// fs = utils.EnsureHostname(serverHostname)(fs)
// }
router.PathPrefix("/ui").Handler(http.StripPrefix("/ui", fs))
2023-03-12 18:17:28 +00:00
router = proxy.BuildFromConfig(router, HTTPConfig.ProxyConfig)
2023-04-01 16:49:54 +00:00
router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/ui", http.StatusMovedPermanently)
}))
2023-03-10 20:59:56 +00:00
if ((HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"] || HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["PROVIDED"]) &&
tlsCert != "" && tlsKey != "") || (HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
2023-03-10 20:59:56 +00:00
utils.Log("TLS certificate exist, starting HTTPS servers and redirecting HTTP to HTTPS")
2023-02-26 22:26:09 +00:00
startHTTPSServer(router, tlsCert, tlsKey)
} else {
utils.Log("TLS certificates do not exists or are disabled, starting HTTP server only")
2023-02-26 22:26:09 +00:00
startHTTPServer(router)
}
}