mirror of
https://github.com/1f349/orchid.git
synced 2024-12-22 08:04:10 +00:00
Start implementation of error emails
This commit is contained in:
parent
7e65015b89
commit
438e44ebfa
@ -1,12 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/1f349/orchid/renewal"
|
import (
|
||||||
|
"github.com/1f349/orchid/renewal"
|
||||||
|
"github.com/1f349/simplemail"
|
||||||
|
)
|
||||||
|
|
||||||
type startUpConfig struct {
|
type startUpConfig struct {
|
||||||
Listen string `yaml:"listen"`
|
Listen string `yaml:"listen"`
|
||||||
Acme acmeConfig `yaml:"acme"`
|
Acme acmeConfig `yaml:"acme"`
|
||||||
LE renewal.LetsEncryptConfig `yaml:"letsEncrypt"`
|
LE renewal.LetsEncryptConfig `yaml:"letsEncrypt"`
|
||||||
Domains []string `yaml:"domains"`
|
Domains []string `yaml:"domains"`
|
||||||
|
Mail mailConfig `json:"mail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type acmeConfig struct {
|
type acmeConfig struct {
|
||||||
@ -14,3 +18,8 @@ type acmeConfig struct {
|
|||||||
CleanUpUrl string `yaml:"cleanUpUrl"`
|
CleanUpUrl string `yaml:"cleanUpUrl"`
|
||||||
RefreshUrl string `yaml:"refreshUrl"`
|
RefreshUrl string `yaml:"refreshUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mailConfig struct {
|
||||||
|
simplemail.Mail
|
||||||
|
To simplemail.FromAddress `json:"to"`
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"embed"
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/1f349/mjwt"
|
"github.com/1f349/mjwt"
|
||||||
"github.com/1f349/orchid"
|
"github.com/1f349/orchid"
|
||||||
@ -9,6 +10,7 @@ import (
|
|||||||
"github.com/1f349/orchid/logger"
|
"github.com/1f349/orchid/logger"
|
||||||
"github.com/1f349/orchid/renewal"
|
"github.com/1f349/orchid/renewal"
|
||||||
"github.com/1f349/orchid/servers"
|
"github.com/1f349/orchid/servers"
|
||||||
|
"github.com/1f349/simplemail"
|
||||||
"github.com/1f349/violet/utils"
|
"github.com/1f349/violet/utils"
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
@ -62,6 +64,9 @@ func (s *serveCmd) Execute(ctx context.Context, f *flag.FlagSet, args ...interfa
|
|||||||
return subcommands.ExitSuccess
|
return subcommands.ExitSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:embed mail-templates/*.go.{html,txt}
|
||||||
|
var mailTemplates embed.FS
|
||||||
|
|
||||||
func normalLoad(conf startUpConfig, wd string) {
|
func normalLoad(conf startUpConfig, wd string) {
|
||||||
// load the MJWT RSA public key from a pem encoded file
|
// load the MJWT RSA public key from a pem encoded file
|
||||||
mJwtVerify, err := mjwt.NewKeyStoreFromPath(filepath.Join(wd, "keys"))
|
mJwtVerify, err := mjwt.NewKeyStoreFromPath(filepath.Join(wd, "keys"))
|
||||||
@ -69,6 +74,11 @@ func normalLoad(conf startUpConfig, wd string) {
|
|||||||
logger.Logger.Fatal("Failed to load MJWT verifier public key from file", "path", filepath.Join(wd, "keys"), "err", err)
|
logger.Logger.Fatal("Failed to load MJWT verifier public key from file", "path", filepath.Join(wd, "keys"), "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mail, err := simplemail.New(&conf.Mail.Mail, "mail", mailTemplates)
|
||||||
|
if err != nil {
|
||||||
|
logger.Logger.Fatal("Failed to load email sender", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
// open sqlite database
|
// open sqlite database
|
||||||
db, err := orchid.InitDB(filepath.Join(wd, "orchid.db.sqlite"))
|
db, err := orchid.InitDB(filepath.Join(wd, "orchid.db.sqlite"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -83,7 +93,7 @@ func normalLoad(conf startUpConfig, wd string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logger.Fatal("HTTP Acme Error", "err", err)
|
logger.Logger.Fatal("HTTP Acme Error", "err", err)
|
||||||
}
|
}
|
||||||
renewalService, err := renewal.NewService(wg, db, acmeProv, conf.LE, certDir, keyDir)
|
renewalService, err := renewal.NewService(wg, db, acmeProv, conf.LE, certDir, keyDir, mail, conf.Mail.To)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logger.Fatal("Service Error", "err", err)
|
logger.Logger.Fatal("Service Error", "err", err)
|
||||||
}
|
}
|
||||||
@ -91,7 +101,7 @@ func normalLoad(conf startUpConfig, wd string) {
|
|||||||
logger.Logger.Info("Starting API server", "listen", srv.Addr)
|
logger.Logger.Info("Starting API server", "listen", srv.Addr)
|
||||||
go utils.RunBackgroundHttp(logger.Logger, srv)
|
go utils.RunBackgroundHttp(logger.Logger, srv)
|
||||||
|
|
||||||
exit_reload.ExitReload("Violet", func() {}, func() {
|
exit_reload.ExitReload("Orchid", func() {}, func() {
|
||||||
// stop renewal service and api server
|
// stop renewal service and api server
|
||||||
renewalService.Shutdown()
|
renewalService.Shutdown()
|
||||||
srv.Close()
|
srv.Close()
|
||||||
|
6
go.mod
6
go.mod
@ -4,6 +4,7 @@ go 1.22
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/1f349/mjwt v0.4.1
|
github.com/1f349/mjwt v0.4.1
|
||||||
|
github.com/1f349/simplemail v0.0.1
|
||||||
github.com/1f349/violet v0.0.14
|
github.com/1f349/violet v0.0.14
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7
|
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||||
github.com/charmbracelet/log v0.4.0
|
github.com/charmbracelet/log v0.4.0
|
||||||
@ -22,6 +23,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/1f349/overlapfs v0.0.1 // indirect
|
||||||
github.com/1f349/rsa-helper v0.0.2 // indirect
|
github.com/1f349/rsa-helper v0.0.2 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||||
@ -29,6 +31,10 @@ require (
|
|||||||
github.com/charmbracelet/lipgloss v0.12.1 // indirect
|
github.com/charmbracelet/lipgloss v0.12.1 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.1.4 // indirect
|
github.com/charmbracelet/x/ansi v0.1.4 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/emersion/go-message v0.18.0 // indirect
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
||||||
|
github.com/emersion/go-smtp v0.20.2 // indirect
|
||||||
|
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
|
21
go.sum
21
go.sum
@ -1,7 +1,11 @@
|
|||||||
github.com/1f349/mjwt v0.4.1 h1:ooCroMMw2kcL5c9L3sLbdtxI0H4/QC8RfTxiloKr+4Y=
|
github.com/1f349/mjwt v0.4.1 h1:ooCroMMw2kcL5c9L3sLbdtxI0H4/QC8RfTxiloKr+4Y=
|
||||||
github.com/1f349/mjwt v0.4.1/go.mod h1:qwnzokkqc7Z9YmKA1m9beI3OZL1GvGYHOQU2rOwoV1M=
|
github.com/1f349/mjwt v0.4.1/go.mod h1:qwnzokkqc7Z9YmKA1m9beI3OZL1GvGYHOQU2rOwoV1M=
|
||||||
|
github.com/1f349/overlapfs v0.0.1 h1:LAxBolrXFAgU0yqZtXg/C/aaPq3eoQSPpBc49BHuTp0=
|
||||||
|
github.com/1f349/overlapfs v0.0.1/go.mod h1:I6aItQycr7nrzplmfNXp/QF9tTmKRSgY3fXmu/7Ky2o=
|
||||||
github.com/1f349/rsa-helper v0.0.2 h1:N/fLQqg5wrjIzG6G4zdwa5Xcv9/jIPutCls9YekZr9U=
|
github.com/1f349/rsa-helper v0.0.2 h1:N/fLQqg5wrjIzG6G4zdwa5Xcv9/jIPutCls9YekZr9U=
|
||||||
github.com/1f349/rsa-helper v0.0.2/go.mod h1:VUQ++1tYYhYrXeOmVFkQ82BegR24HQEJHl5lHbjg7yg=
|
github.com/1f349/rsa-helper v0.0.2/go.mod h1:VUQ++1tYYhYrXeOmVFkQ82BegR24HQEJHl5lHbjg7yg=
|
||||||
|
github.com/1f349/simplemail v0.0.1 h1:/euBoIpXVall46loDDTjkpEFHEWo213peBBE77n8kRY=
|
||||||
|
github.com/1f349/simplemail v0.0.1/go.mod h1:7QNDldEOFto/4rsbk5KZGYBOK3Wem2/Bv2uQ5YoczP4=
|
||||||
github.com/1f349/violet v0.0.14 h1:MpBZ4n1dJjdiIwYMTfh0PBIFll3kjqowxR6DLasafqE=
|
github.com/1f349/violet v0.0.14 h1:MpBZ4n1dJjdiIwYMTfh0PBIFll3kjqowxR6DLasafqE=
|
||||||
github.com/1f349/violet v0.0.14/go.mod h1:iAREhm+wxnGXkmuvmBhOuhUx2T7/5w7stLYNgQGbqC8=
|
github.com/1f349/violet v0.0.14/go.mod h1:iAREhm+wxnGXkmuvmBhOuhUx2T7/5w7stLYNgQGbqC8=
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
||||||
@ -25,6 +29,15 @@ github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/emersion/go-message v0.18.0 h1:7LxAXHRpSeoO/Wom3ZApVZYG7c3d17yCScYce8WiXA8=
|
||||||
|
github.com/emersion/go-message v0.18.0/go.mod h1:Zi69ACvzaoV/MBnrxfVBPV3xWEuCmC2nEN39oJF4B8A=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||||
|
github.com/emersion/go-smtp v0.20.2 h1:peX42Qnh5Q0q3vrAnRy43R/JwTnnv75AebxbkTL7Ia4=
|
||||||
|
github.com/emersion/go-smtp v0.20.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||||
|
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
|
||||||
|
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||||
github.com/go-acme/lego/v4 v4.17.3 h1:5our7Qdyik0abag40abdmQuytq97iweaNHFMT4pYDnQ=
|
github.com/go-acme/lego/v4 v4.17.3 h1:5our7Qdyik0abag40abdmQuytq97iweaNHFMT4pYDnQ=
|
||||||
github.com/go-acme/lego/v4 v4.17.3/go.mod h1:Ol6l04hnmavqVHKYS/ByhXXqE64x8yVYhomha82uAUk=
|
github.com/go-acme/lego/v4 v4.17.3/go.mod h1:Ol6l04hnmavqVHKYS/ByhXXqE64x8yVYhomha82uAUk=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
||||||
@ -114,15 +127,18 @@ golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn5
|
|||||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -132,22 +148,27 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
0
mail-templates/failed-to-find.go.html
Normal file
0
mail-templates/failed-to-find.go.html
Normal file
0
mail-templates/failed-to-find.go.txt
Normal file
0
mail-templates/failed-to-find.go.txt
Normal file
@ -13,6 +13,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/1f349/orchid/database"
|
"github.com/1f349/orchid/database"
|
||||||
"github.com/1f349/orchid/pebble"
|
"github.com/1f349/orchid/pebble"
|
||||||
|
"github.com/1f349/simplemail"
|
||||||
"github.com/go-acme/lego/v4/certificate"
|
"github.com/go-acme/lego/v4/certificate"
|
||||||
"github.com/go-acme/lego/v4/challenge"
|
"github.com/go-acme/lego/v4/challenge"
|
||||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||||
@ -64,10 +65,12 @@ type Service struct {
|
|||||||
keyDir string
|
keyDir string
|
||||||
insecure bool
|
insecure bool
|
||||||
client *lego.Client
|
client *lego.Client
|
||||||
|
mail *simplemail.SimpleMail
|
||||||
|
mailTo simplemail.FromAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService creates a new certificate renewal service.
|
// NewService creates a new certificate renewal service.
|
||||||
func NewService(wg *sync.WaitGroup, db *database.Queries, httpAcme challenge.Provider, leConfig LetsEncryptConfig, certDir, keyDir string) (*Service, error) {
|
func NewService(wg *sync.WaitGroup, db *database.Queries, httpAcme challenge.Provider, leConfig LetsEncryptConfig, certDir, keyDir string, mail *simplemail.SimpleMail, mailTo simplemail.FromAddress) (*Service, error) {
|
||||||
s := &Service{
|
s := &Service{
|
||||||
db: db,
|
db: db,
|
||||||
httpAcme: httpAcme,
|
httpAcme: httpAcme,
|
||||||
@ -80,6 +83,8 @@ func NewService(wg *sync.WaitGroup, db *database.Queries, httpAcme challenge.Pro
|
|||||||
certDir: certDir,
|
certDir: certDir,
|
||||||
keyDir: keyDir,
|
keyDir: keyDir,
|
||||||
insecure: leConfig.insecure,
|
insecure: leConfig.insecure,
|
||||||
|
mail: mail,
|
||||||
|
mailTo: mailTo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// make certDir and keyDir
|
// make certDir and keyDir
|
||||||
@ -124,6 +129,26 @@ func (s *Service) Shutdown() {
|
|||||||
close(s.certDone)
|
close(s.certDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) sendErrorEmail(templateName, subject string, data map[string]any, err error) error {
|
||||||
|
// sending mail is disabled
|
||||||
|
if s.mail == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// create empty data map
|
||||||
|
if data == nil {
|
||||||
|
data = make(map[string]any)
|
||||||
|
}
|
||||||
|
data["error"] = err
|
||||||
|
|
||||||
|
// send email and listen for errors
|
||||||
|
mailErr := s.mail.Send(templateName, subject, s.mailTo.Address, data)
|
||||||
|
if mailErr != nil {
|
||||||
|
return fmt.Errorf("failed to send error email for: %w because: %w", err, mailErr)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// resolveLEPrivKey resolves the private key for the LetsEncrypt account.
|
// resolveLEPrivKey resolves the private key for the LetsEncrypt account.
|
||||||
// If the string is a path to a file then the contents of the file is read.
|
// If the string is a path to a file then the contents of the file is read.
|
||||||
func (s *Service) resolveLEPrivKey(a string) error {
|
func (s *Service) resolveLEPrivKey(a string) error {
|
||||||
@ -255,7 +280,7 @@ func (s *Service) renewalCheck() error {
|
|||||||
// check for running out certificates in the database
|
// check for running out certificates in the database
|
||||||
localData, err := s.findNextCertificateToRenew()
|
localData, err := s.findNextCertificateToRenew()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to find a certificate to renew: %w", err)
|
return s.sendErrorEmail("failed-to-find", "Failed to find a certificate to renew", nil, fmt.Errorf("failed to find a certificate to renew: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// no certificates to update
|
// no certificates to update
|
||||||
@ -268,7 +293,12 @@ func (s *Service) renewalCheck() error {
|
|||||||
err = s.renewCert(localData)
|
err = s.renewCert(localData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Logger.Debug("Failed to renew certificate", "err", err)
|
Logger.Debug("Failed to renew certificate", "err", err)
|
||||||
return err
|
return s.sendErrorEmail("failed-to-renew", "Failed to renew a certificate", map[string]any{
|
||||||
|
"id": localData.id,
|
||||||
|
"dns-name": localData.dns.name,
|
||||||
|
"domains": localData.domains,
|
||||||
|
"not-after": localData.notAfter,
|
||||||
|
}, fmt.Errorf("failed to renew a certificate: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// renew succeeded
|
// renew succeeded
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/1f349/orchid/logger"
|
"github.com/1f349/orchid/logger"
|
||||||
"github.com/1f349/orchid/pebble"
|
"github.com/1f349/orchid/pebble"
|
||||||
"github.com/1f349/orchid/test"
|
"github.com/1f349/orchid/test"
|
||||||
|
"github.com/1f349/simplemail"
|
||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
"github.com/go-acme/lego/v4/lego"
|
"github.com/go-acme/lego/v4/lego"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -125,7 +126,7 @@ func setupPebbleTest(t *testing.T, serverTls *certgen.CertGen) (*Service, *sql.D
|
|||||||
Directory: "https://localhost:14000/dir",
|
Directory: "https://localhost:14000/dir",
|
||||||
Certificate: "insecure",
|
Certificate: "insecure",
|
||||||
insecure: true,
|
insecure: true,
|
||||||
}, certDir, keyDir)
|
}, certDir, keyDir, nil, simplemail.FromAddress{})
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -170,7 +171,7 @@ func TestPebbleRenewal(t *testing.T) {
|
|||||||
_, err := db2.Exec("DELETE FROM certificate_domains")
|
_, err := db2.Exec("DELETE FROM certificate_domains")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_, err = db2.Exec(`INSERT INTO certificates (owner, dns, auto_renew, active, renewing, renew_failed, not_after, updated_at) VALUES (1, 1, 1, 1, 0, 0, "2000-01-01 00:00:00+00:00", "2000-01-01 00:00:00+00:00")`)
|
_, err = db2.Exec(`INSERT INTO certificates (owner, dns, auto_renew, active, renewing, renew_failed, not_after, updated_at) VALUES (1, 1, 1, 1, 0, 0, '2000-01-01 00:00:00+00:00', '2000-01-01 00:00:00+00:00')`)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
for _, j := range i.domains {
|
for _, j := range i.domains {
|
||||||
_, err = db2.Exec(`INSERT INTO certificate_domains (cert_id, domain) VALUES (1, ?)`, j)
|
_, err = db2.Exec(`INSERT INTO certificate_domains (cert_id, domain) VALUES (1, ?)`, j)
|
||||||
|
Loading…
Reference in New Issue
Block a user