[release] v0.9.0-unstable

This commit is contained in:
Yann Stepienik 2023-07-01 16:32:21 +01:00
parent 004c59b00d
commit d0eedf7cc1
10 changed files with 765 additions and 548 deletions

View file

@ -79,6 +79,7 @@ const ConfigManagement = () => {
HTTPSCertificateMode: config.HTTPConfig.HTTPSCertificateMode,
DNSChallengeProvider: config.HTTPConfig.DNSChallengeProvider,
DNSChallengeConfig: config.HTTPConfig.DNSChallengeConfig,
ForceHTTPSCertificateRenewal: config.HTTPConfig.ForceHTTPSCertificateRenewal,
Email_Enabled: config.EmailConfig.Enabled,
Email_Host: config.EmailConfig.Host,
@ -120,6 +121,7 @@ const ConfigManagement = () => {
HTTPSCertificateMode: values.HTTPSCertificateMode,
DNSChallengeProvider: values.DNSChallengeProvider,
DNSChallengeConfig: values.DNSChallengeConfig,
ForceHTTPSCertificateRenewal: values.ForceHTTPSCertificateRenewal,
},
EmailConfig: {
...config.EmailConfig,
@ -517,6 +519,9 @@ const ConfigManagement = () => {
name="HTTPSCertificateMode"
label="HTTPS Certificates"
formik={formik}
onChange={(e) => {
formik.setFieldValue("ForceHTTPSCertificateRenewal", true);
}}
options={[
["LETSENCRYPT", "Automatically generate certificates using Let's Encrypt (Recommended)"],
["SELFSIGNED", "Locally self-sign certificates (unsecure)"],
@ -527,6 +532,9 @@ const ConfigManagement = () => {
<CosmosCheckbox
label={"Use Wildcard Certificate for *." + formik.values.Hostname}
onChange={(e) => {
formik.setFieldValue("ForceHTTPSCertificateRenewal", true);
}}
name="UseWildcardCertificate"
formik={formik}
/>
@ -534,6 +542,9 @@ const ConfigManagement = () => {
{formik.values.HTTPSCertificateMode === "LETSENCRYPT" && (
<CosmosInputText
name="SSLEmail"
onChange={(e) => {
formik.setFieldValue("ForceHTTPSCertificateRenewal", true);
}}
label="Email address for Let's Encrypt"
formik={formik}
/>
@ -543,6 +554,9 @@ const ConfigManagement = () => {
{
formik.values.HTTPSCertificateMode === "LETSENCRYPT" && (
<DnsChallengeComp
onChange={(e) => {
formik.setFieldValue("ForceHTTPSCertificateRenewal", true);
}}
label="Pick a DNS provider (if you are using a DNS Challenge, otherwise leave empty)"
name="DNSChallengeProvider"
configName="DNSChallengeConfig"

153
go.mod
View file

@ -6,8 +6,8 @@ require (
github.com/Masterminds/semver v1.5.0
github.com/docker/docker v23.0.1+incompatible
github.com/docker/go-connections v0.4.0
github.com/foomo/simplecert v1.8.4
github.com/foomo/tlsconfig v0.0.0-20180418120404-b67861b076c9
github.com/go-acme/lego/v4 v4.12.3
github.com/go-chi/chi v4.0.2+incompatible
github.com/go-chi/httprate v0.7.1
github.com/go-playground/validator/v10 v10.12.0
@ -28,99 +28,111 @@ require (
)
require (
cloud.google.com/go v0.75.0 // indirect
github.com/Azure/azure-sdk-for-go v50.1.0+incompatible // indirect
cloud.google.com/go/compute v1.18.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.17 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.10 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.6 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 // indirect
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/PuerkitoBio/goquery v1.6.0 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.0.1 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.869 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.1 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/andybalholm/cascadia v1.1.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
github.com/aws/aws-sdk-go v1.36.29 // indirect
github.com/aws/aws-sdk-go v1.39.0 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/cenkalti/backoff/v4 v4.1.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cloudflare/cloudflare-go v0.13.7 // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/civo/civogo v0.3.11 // indirect
github.com/cloudflare/cloudflare-go v0.49.0 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect
github.com/cristalhq/jwt/v4 v4.0.2 // indirect
github.com/dave/jennifer v1.4.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deepmap/oapi-codegen v1.4.2 // indirect
github.com/deepmap/oapi-codegen v1.9.1 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dnsimple/dnsimple-go v0.63.0 // indirect
github.com/dnsimple/dnsimple-go v0.71.1 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/ecordell/optgen v0.0.6 // indirect
github.com/exoscale/egoscale v0.40.0 // indirect
github.com/exoscale/egoscale v0.90.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/form3tech-oss/jwt-go v3.2.2+incompatible // indirect
github.com/friendsofgo/errors v0.9.2 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-acme/lego/v4 v4.1.3 // indirect
github.com/go-errors/errors v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-resty/resty/v2 v2.4.0 // indirect
github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 // indirect
github.com/gogo/protobuf v1.2.1 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.4.3 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/goodhosts/hostsfile v0.0.7 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/uuid v1.1.5 // indirect
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/gophercloud/gophercloud v0.15.0 // indirect
github.com/gophercloud/utils v0.0.0-20210113034859-6f548432055a // indirect
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
github.com/hashicorp/go-retryablehttp v0.6.8 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
github.com/gophercloud/gophercloud v1.0.0 // indirect
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jarcoal/httpmock v1.0.7 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.10 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b // indirect
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b // indirect
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
github.com/labbsr0x/goh v1.0.1 // indirect
github.com/leodido/go-urn v1.2.2 // indirect
github.com/linode/linodego v0.24.2 // indirect
github.com/liquidweb/liquidweb-go v1.6.1 // indirect
github.com/linode/linodego v1.9.1 // indirect
github.com/liquidweb/go-lwApi v0.0.5 // indirect
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
github.com/liquidweb/liquidweb-go v1.6.3 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.1 // indirect
github.com/magiconair/properties v1.8.4 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/goveralls v0.0.6 // indirect
github.com/miekg/dns v1.1.35 // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/mimuret/golang-iij-dpf v0.7.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
github.com/nrdcg/auroradns v1.0.1 // indirect
github.com/nrdcg/desec v0.5.0 // indirect
github.com/nrdcg/auroradns v1.1.0 // indirect
github.com/nrdcg/desec v0.6.0 // indirect
github.com/nrdcg/dnspod-go v0.4.0 // indirect
github.com/nrdcg/freemyip v0.2.0 // indirect
github.com/nrdcg/goinwx v0.8.1 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/porkbun v0.1.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
@ -132,46 +144,61 @@ require (
github.com/ovh/go-ovh v1.1.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pborman/uuid v1.2.0 // indirect
github.com/pelletier/go-toml v1.8.0 // indirect
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/sacloud/libsacloud v1.36.2 // indirect
github.com/sirupsen/logrus v1.7.0 // indirect
github.com/spf13/afero v1.3.2 // indirect
github.com/sacloud/api-client-go v0.2.1 // indirect
github.com/sacloud/go-http v0.1.2 // indirect
github.com/sacloud/iaas-api-go v1.3.2 // indirect
github.com/sacloud/packages-go v0.0.5 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.0.6 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/spf13/afero v1.4.1 // indirect
github.com/spf13/cast v1.3.2-0.20200723214538-8d17101741c8 // indirect
github.com/spf13/cobra v1.0.0 // indirect
github.com/spf13/cobra v1.1.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.3 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/transip/gotransip/v6 v6.5.0 // indirect
github.com/vultr/govultr v1.1.1 // indirect
github.com/transip/gotransip/v6 v6.17.0 // indirect
github.com/ultradns/ultradns-go-sdk v1.4.0-20221107152238-f3f1d1d // indirect
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opencensus.io v0.22.5 // indirect
go.uber.org/ratelimit v0.1.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3 // indirect
golang.org/x/oauth2 v0.6.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.6.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/api v0.36.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.111.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210119180700-e258113e47cc // indirect
google.golang.org/grpc v1.36.0 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.4.3 // indirect
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect
gopkg.in/ns1/ns1-go.v2 v2.6.5 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

749
go.sum

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.8.11",
"version": "0.9.0-unstable",
"description": "",
"main": "test-server.js",
"bugs": {
@ -63,7 +63,7 @@
"scripts": {
"client": "vite",
"client-build": "vite build --base=/cosmos-ui/",
"start": "env CONFIG_FILE=./config_dev.json EZ=UTC build/cosmos",
"start": "env CONFIG_FILE=./config_dev.json EZ=UTC ACME_STAGING=true build/cosmos",
"build": "sh build.sh",
"dev": "npm run build && npm run start",
"dockerdevbuild": "sh build.sh && docker build -f dockerfile.local --tag cosmos-dev .",

View file

@ -101,11 +101,30 @@ func checkUpdatesAvailable() {
utils.UpdateAvailable = docker.CheckUpdatesAvailable()
}
func checkCerts() {
config := utils.GetMainConfig()
HTTPConfig := config.HTTPConfig
if (
HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"] ||
HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
utils.Log("Checking certificates for renewal")
if !CertificateIsValid(HTTPConfig.TLSValidUntil) {
utils.Log("Certificates are not valid anymore, renewing")
RestartServer()
}
}
}
func CRON() {
go func() {
gocron.Every(1).Day().At("00:00").Do(checkVersion)
<-gocron.Start()
}()
go func() {
gocron.Every(1).Day().At("01:00").Do(checkCerts)
<-gocron.Start()
}()
go func() {
gocron.Every(6).Hours().Do(checkUpdatesAvailable)
<-gocron.Start()

View file

@ -87,7 +87,9 @@ func ConfigApiPatch(w http.ResponseWriter, req *http.Request) {
config.HTTPConfig.ProxyConfig.Routes = routes
utils.SaveConfigTofile(config)
utils.NeedsRestart = true
//utils.NeedsRestart = true
utils.RestartHTTPServer()
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",

View file

@ -18,81 +18,53 @@ import (
"github.com/go-chi/httprate"
"crypto/tls"
spa "github.com/roberthodgen/spa-server"
"github.com/foomo/simplecert"
"github.com/foomo/tlsconfig"
"context"
)
var serverPortHTTP = ""
var serverPortHTTPS = ""
var HTTPServer *http.Server
func startHTTPServer(router *mux.Router) {
utils.Log("Listening to HTTP on : 0.0.0.0:" + serverPortHTTP)
var errServ error
for(errServ == http.ErrServerClosed || errServ == nil) {
HTTPServer = &http.Server{
Addr: "0.0.0.0:" + serverPortHTTP,
ReadTimeout: 0,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 0,
IdleTimeout: 30 * time.Second,
Handler: router,
DisableGeneralOptionsHandler: true,
}
docker.CheckPorts()
utils.Log("Listening to HTTP on : 0.0.0.0:" + serverPortHTTP)
err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, router)
docker.CheckPorts()
if err != nil {
utils.Fatal("Listening to HTTP", err)
errServ = HTTPServer.ListenAndServe()
if errServ != nil && errServ != http.ErrServerClosed {
utils.Fatal("Listening to HTTPS", errServ)
}
utils.Log("HTTP Server closed. Restarting.")
errServ = nil
router = InitServer()
}
}
func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
config := utils.GetMainConfig()
cfg := simplecert.Default
if config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"] {
cfg.CacheDir = "/config/certificates"
cfg.SSLEmail = config.HTTPConfig.SSLEmail
cfg.HTTPAddress = "0.0.0.0:"+serverPortHTTP
cfg.TLSAddress = "0.0.0.0:"+serverPortHTTPS
if config.HTTPConfig.DNSChallengeProvider != "" {
utils.Log("Using DNS Challenge with Provider: " + config.HTTPConfig.DNSChallengeProvider)
cfg.DNSProvider = config.HTTPConfig.DNSChallengeProvider
cfg.Domains = utils.GetAllHostnames(true, false)
} else {
cfg.Domains = utils.LetsEncryptValidOnly(utils.GetAllHostnames(true, false))
}
}
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"]) {
if(config.HTTPConfig.DNSChallengeProvider != "") {
newEnv := config.HTTPConfig.DNSChallengeConfig
for key, value := range newEnv {
os.Setenv(key, value)
}
}
certReloader, errSimCert = simplecert.Init(cfg, nil)
if errSimCert != nil {
// Temporary before we have a better way to handle this
utils.Error("Failed to Init Let's Encrypt. HTTPS wont renew", errSimCert)
startHTTPServer(router)
return
}
}
//config := utils.GetMainConfig()
utils.IsHTTPS = true
// Redirect ports
docker.CheckPorts()
// redirect http to https
go (func () {
httpRouter := mux.NewRouter()
// add support for internal OpenID requests
// if os.Getenv("HOSTNAME") != "" {
// authorizationserver.RegisterHandlers(httpRouter.Host(os.Getenv("HOSTNAME")).Subrouter())
// }
httpRouter.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// change port in host
if strings.HasSuffix(r.Host, ":" + serverPortHTTP) {
@ -106,7 +78,6 @@ func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
http.Redirect(w, r, "https://"+r.Host+r.URL.String(), http.StatusMovedPermanently)
})
// err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, http.HandlerFunc(simplecert.Redirect))
err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, httpRouter)
if err != nil {
@ -119,34 +90,47 @@ func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
tlsConf := tlsconfig.NewServerTLSConfig(tlsconfig.TLSModeServerStrict)
if(config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
/*if(config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
tlsConf.GetCertificate = certReloader.GetCertificateFunc()
} else {
} else {*/
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: "0.0.0.0:" + serverPortHTTPS,
ReadTimeout: 0,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 0,
IdleTimeout: 30 * time.Second,
Handler: router,
DisableGeneralOptionsHandler: true,
}
//}
// start https server
errServ := server.ListenAndServeTLS("", "")
var errServ error
if errServ != nil {
utils.Fatal("Listening to HTTPS", errServ)
for(errServ == http.ErrServerClosed || errServ == nil) {
HTTPServer = &http.Server{
TLSConfig: tlsConf,
Addr: "0.0.0.0:" + serverPortHTTPS,
ReadTimeout: 0,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 0,
IdleTimeout: 30 * time.Second,
Handler: router,
DisableGeneralOptionsHandler: true,
}
// Redirect ports
docker.CheckPorts()
utils.Log("Now listening to HTTPS on :" + serverPortHTTPS)
errServ = HTTPServer.ListenAndServeTLS("", "")
if errServ != nil && errServ != http.ErrServerClosed {
utils.Fatal("Listening to HTTPS", errServ)
}
utils.Log("HTTPS Server closed. Restarting.")
errServ = nil
router = InitServer()
}
}
@ -196,7 +180,18 @@ func SecureAPI(userRouter *mux.Router, public bool) {
))
}
func StartServer() {
func CertificateIsValid(validUntil time.Time) bool {
// allow 5 days of leeway
isValid := time.Now().Add(5 * 24 * time.Hour).Before(validUntil)
if !isValid {
utils.Log("Certificate is not valid anymore. Needs refresh")
}
return isValid
}
func InitServer() *mux.Router {
utils.RestartHTTPServer = RestartServer
baseMainConfig := utils.GetBaseMainConfig()
config := utils.GetMainConfig()
HTTPConfig := config.HTTPConfig
@ -208,20 +203,65 @@ func StartServer() {
domains := utils.GetAllHostnames(true, false)
oldDomains := baseMainConfig.HTTPConfig.TLSKeyHostsCached
falledBack := false
NeedsRefresh := (tlsCert == "" || tlsKey == "") || !utils.StringArrayEquals(domains, oldDomains)
NeedsRefresh := baseMainConfig.HTTPConfig.ForceHTTPSCertificateRenewal || (tlsCert == "" || tlsKey == "") || !utils.StringArrayEquals(domains, oldDomains) || !CertificateIsValid(baseMainConfig.HTTPConfig.TLSValidUntil)
// If we have a certificate, we can fallback to it if necessary
CanFallback := tlsCert != "" && tlsKey != "" &&
len(config.HTTPConfig.TLSKeyHostsCached) > 0 &&
config.HTTPConfig.TLSKeyHostsCached[0] == config.HTTPConfig.Hostname &&
CertificateIsValid(baseMainConfig.HTTPConfig.TLSValidUntil)
if(NeedsRefresh && config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
if(config.HTTPConfig.DNSChallengeProvider != "") {
newEnv := config.HTTPConfig.DNSChallengeConfig
for key, value := range newEnv {
os.Setenv(key, value)
}
}
// Get Certificates
pub, priv := utils.DoLetsEncrypt()
if(pub == "" || priv == "") {
if(!CanFallback) {
utils.Error("Getting TLS certificate. Fallback to SELFSIGNED certificates", nil)
HTTPConfig.HTTPSCertificateMode = utils.HTTPSCertModeList["SELFSIGNED"]
falledBack = true
} else {
utils.Error("Getting TLS certificate. Fallback to previous certificate", nil)
}
} else {
baseMainConfig.HTTPConfig.TLSCert = pub
baseMainConfig.HTTPConfig.TLSKey = priv
baseMainConfig.HTTPConfig.TLSKeyHostsCached = domains
baseMainConfig.HTTPConfig.TLSValidUntil = time.Now().AddDate(0, 0, 90)
baseMainConfig.HTTPConfig.ForceHTTPSCertificateRenewal = false
utils.SetBaseMainConfig(baseMainConfig)
utils.Log("Saved new LETSENCRYPT TLS certificate")
tlsCert = pub
tlsKey = priv
}
}
if(NeedsRefresh && HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"]) {
utils.Log("Generating new TLS certificate for domains: " + strings.Join(domains, ", "))
pub, priv := utils.GenerateRSAWebCertificates(domains)
baseMainConfig.HTTPConfig.TLSCert = pub
baseMainConfig.HTTPConfig.TLSKey = priv
baseMainConfig.HTTPConfig.TLSKeyHostsCached = domains
if !falledBack {
baseMainConfig.HTTPConfig.TLSCert = pub
baseMainConfig.HTTPConfig.TLSKey = priv
baseMainConfig.HTTPConfig.TLSKeyHostsCached = domains
baseMainConfig.HTTPConfig.TLSValidUntil = time.Now().AddDate(0, 0, 364)
baseMainConfig.HTTPConfig.ForceHTTPSCertificateRenewal = false
utils.SetBaseMainConfig(baseMainConfig)
utils.Log("Saved new TLS certificate")
utils.SetBaseMainConfig(baseMainConfig)
utils.Log("Saved new SELFISGNED TLS certificate")
}
tlsCert = pub
tlsKey = priv
@ -238,12 +278,11 @@ func StartServer() {
utils.Log("Saved new Auth ED25519 certificate")
}
utils.Log("Initialising HTTP(S) Router and all routes")
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/logo", SendLogo)
// need rewrite bc it catches too many things and prevent
// client to be notified of the error
router.Use(middleware.Logger)
router.Use(utils.SetSecurityHeaders)
@ -324,11 +363,6 @@ func StartServer() {
router.PathPrefix("/cosmos-ui").Handler(http.StripPrefix("/cosmos-ui", fs))
// temporary message to help people migrate version. DELETE IN NEXT VERSION
router.HandleFunc("/ui", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("You are seeing this message because the UI was moved from /ui to /cosmos-ui, in order to fix compatibility with apps like OpenSense who also use /ui. The issue is that your browser still has the old UI URL cached. Please empty your browser's cache and reload the page. Also, make sure you don't have a bookmark with the /ui in the URL. This message will disappear in the next version of Cosmos, to solve the compatibility issue. Sorry for the inconvenience."))
})
router = proxy.BuildFromConfig(router, HTTPConfig.ProxyConfig)
router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -347,8 +381,24 @@ func StartServer() {
authorizationserver.RegisterHandlers(wellKnownRouter, userRouter, serverRouter)
if ((HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"] || HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["PROVIDED"]) &&
tlsCert != "" && tlsKey != "") || (HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
return router
}
func StartServer() {
config := utils.GetMainConfig()
HTTPConfig := config.HTTPConfig
var tlsCert = HTTPConfig.TLSCert
var tlsKey= HTTPConfig.TLSKey
router := InitServer()
if (
(
HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"] ||
HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["PROVIDED"] ||
HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) &&
tlsCert != "" && tlsKey != "") {
utils.Log("TLS certificate exist, starting HTTPS servers and redirecting HTTP to HTTPS")
startHTTPSServer(router, tlsCert, tlsKey)
} else {
@ -356,3 +406,14 @@ func StartServer() {
startHTTPServer(router)
}
}
func RestartServer() {
utils.Log("Restarting HTTP Server...")
LoadConfig()
go func() {
HTTPServer.Shutdown(context.Background())
}()
utils.Log("HTTP Server stopped. Restarting...")
}

View file

@ -6,10 +6,22 @@ import (
"math/big"
"time"
"crypto/rand"
"crypto"
"crypto/rsa"
"crypto/ed25519"
"crypto/x509/pkix"
"encoding/asn1"
"crypto/ecdsa"
"crypto/elliptic"
"os"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/http01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
"github.com/go-acme/lego/v4/providers/dns"
)
func GenerateRSAWebCertificates(domains []string) (string, string) {
@ -108,3 +120,112 @@ func GenerateEd25519Certificates() (string, string) {
return string(pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: bpub})), string(pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: bpriv}))
}
type CertUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *CertUser) GetEmail() string {
return u.Email
}
func (u CertUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *CertUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}
func DoLetsEncrypt() (string, string) {
config := GetMainConfig()
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
Error("LETSENCRYPT_ECDSA", err)
return "", ""
}
myUser := CertUser{
Email: config.HTTPConfig.SSLEmail,
key: privateKey,
}
certConfig := lego.NewConfig(&myUser)
if os.Getenv("ACME_STAGING") == "true" {
certConfig.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
} else {
certConfig.CADirURL = "https://acme-v02.api.letsencrypt.org/directory"
}
certConfig.Certificate.KeyType = certcrypto.RSA2048
client, err := lego.NewClient(certConfig)
if err != nil {
Error("LETSENCRYPT_NEW", err)
return "", ""
}
if config.HTTPConfig.DNSChallengeProvider != "" {
provider, err := dns.NewDNSChallengeProviderByName(config.HTTPConfig.DNSChallengeProvider)
if err != nil {
Error("LETSENCRYPT_DNS", err)
return "", ""
}
err = client.Challenge.SetDNS01Provider(provider)
}
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", config.HTTPConfig.HTTPPort))
if err != nil {
Error("LETSENCRYPT_HTTP01", err)
return "", ""
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", config.HTTPConfig.HTTPSPort))
if err != nil {
Error("LETSENCRYPT_TLS01", err)
return "", ""
}
// New users will need to register
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
Error("LETSENCRYPT_REGISTER", err)
return "", ""
}
myUser.Registration = reg
request := certificate.ObtainRequest{
Domains: LetsEncryptValidOnly(GetAllHostnames(true, false)),
Bundle: true,
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
Error("LETSENCRYPT_OBTAIN", err)
return "", ""
}
// return cert and key
return string(certificates.Certificate), string(certificates.PrivateKey)
}
// You'll need a user or account type that implements acme.User
type MyUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}

View file

@ -105,11 +105,13 @@ type HTTPConfig struct {
TLSCert string `validate:"omitempty,contains=\n`
TLSKey string
TLSKeyHostsCached []string
TLSValidUntil time.Time
AuthPrivateKey string
AuthPublicKey string
GenerateMissingAuthCert bool
HTTPSCertificateMode string
DNSChallengeProvider string
ForceHTTPSCertificateRenewal bool
HTTPPort string `validate:"required,containsany=0123456789,min=1,max=6"`
HTTPSPort string `validate:"required,containsany=0123456789,min=1,max=6"`
ProxyConfig ProxyConfig

View file

@ -31,6 +31,8 @@ var NeedsRestart = false
var UpdateAvailable = map[string]bool{}
var RestartHTTPServer func()
var DefaultConfig = Config{
LoggingLevel: "INFO",
NewInstall: true,
@ -352,8 +354,8 @@ func GetAllHostnames(applyWildCard bool, removePorts bool) []string {
if applyWildCard && MainConfig.HTTPConfig.UseWildcardCertificate {
filteredHostnames := []string{
"*." + mainHostname,
mainHostname,
"*." + mainHostname,
}
for _, hostname := range uniqueHostnames {