mirror of
https://github.com/openziti/zrok.git
synced 2024-11-22 16:13:47 +01:00
roughed in limit warning email actions (#276)
This commit is contained in:
parent
bb61bdb664
commit
d279fbb8cb
@ -1,6 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/openziti/zrok/controller/emailUi"
|
||||||
"github.com/openziti/zrok/controller/env"
|
"github.com/openziti/zrok/controller/env"
|
||||||
"github.com/openziti/zrok/controller/limits"
|
"github.com/openziti/zrok/controller/limits"
|
||||||
"github.com/openziti/zrok/controller/metrics"
|
"github.com/openziti/zrok/controller/metrics"
|
||||||
@ -19,7 +20,7 @@ type Config struct {
|
|||||||
Admin *AdminConfig
|
Admin *AdminConfig
|
||||||
Bridge *metrics.BridgeConfig
|
Bridge *metrics.BridgeConfig
|
||||||
Endpoint *EndpointConfig
|
Endpoint *EndpointConfig
|
||||||
Email *EmailConfig
|
Email *emailUi.Config
|
||||||
Limits *limits.Config
|
Limits *limits.Config
|
||||||
Maintenance *MaintenanceConfig
|
Maintenance *MaintenanceConfig
|
||||||
Metrics *metrics.Config
|
Metrics *metrics.Config
|
||||||
@ -39,14 +40,6 @@ type EndpointConfig struct {
|
|||||||
Port int
|
Port int
|
||||||
}
|
}
|
||||||
|
|
||||||
type EmailConfig struct {
|
|
||||||
Host string
|
|
||||||
Port int
|
|
||||||
Username string
|
|
||||||
Password string `cf:"+secret"`
|
|
||||||
From string
|
|
||||||
}
|
|
||||||
|
|
||||||
type RegistrationConfig struct {
|
type RegistrationConfig struct {
|
||||||
RegistrationUrlTemplate string
|
RegistrationUrlTemplate string
|
||||||
TokenStrategy string
|
TokenStrategy string
|
||||||
|
@ -84,7 +84,7 @@ func Run(inCfg *config.Config) error {
|
|||||||
defer func() { ma.Stop() }()
|
defer func() { ma.Stop() }()
|
||||||
|
|
||||||
if cfg.Limits != nil && cfg.Limits.Enforcing {
|
if cfg.Limits != nil && cfg.Limits.Enforcing {
|
||||||
limitsAgent, err = limits.NewAgent(cfg.Limits, cfg.Metrics.Influx, cfg.Ziti, str)
|
limitsAgent, err = limits.NewAgent(cfg.Limits, cfg.Metrics.Influx, cfg.Ziti, cfg.Email, str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error creating limits agent")
|
return errors.Wrap(err, "error creating limits agent")
|
||||||
}
|
}
|
||||||
|
9
controller/emailUi/config.go
Normal file
9
controller/emailUi/config.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package emailUi
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Username string
|
||||||
|
Password string `cf:"+secret"`
|
||||||
|
From string
|
||||||
|
}
|
24
controller/emailUi/model.go
Normal file
24
controller/emailUi/model.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package emailUi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"html/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WarningEmail struct {
|
||||||
|
EmailAddress string
|
||||||
|
Detail string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (we WarningEmail) MergeTemplate(filename string) (string, error) {
|
||||||
|
t, err := template.ParseFS(FS, filename)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrapf(err, "error parsing warning email template '%v'", filename)
|
||||||
|
}
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
if err := t.Execute(buf, we); err != nil {
|
||||||
|
return "", errors.Wrapf(err, "error executing warning email template '%v'", filename)
|
||||||
|
}
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
@ -3,20 +3,28 @@ package limits
|
|||||||
import (
|
import (
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/openziti/edge/rest_management_api_client"
|
"github.com/openziti/edge/rest_management_api_client"
|
||||||
|
"github.com/openziti/zrok/controller/emailUi"
|
||||||
"github.com/openziti/zrok/controller/store"
|
"github.com/openziti/zrok/controller/store"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type accountWarningAction struct {
|
type accountWarningAction struct {
|
||||||
str *store.Store
|
str *store.Store
|
||||||
edge *rest_management_api_client.ZitiEdgeManagement
|
edge *rest_management_api_client.ZitiEdgeManagement
|
||||||
|
cfg *emailUi.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAccountWarningAction(str *store.Store, edge *rest_management_api_client.ZitiEdgeManagement) *accountWarningAction {
|
func newAccountWarningAction(cfg *emailUi.Config, str *store.Store, edge *rest_management_api_client.ZitiEdgeManagement) *accountWarningAction {
|
||||||
return &accountWarningAction{str, edge}
|
return &accountWarningAction{str, edge, cfg}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *accountWarningAction) HandleAccount(acct *store.Account, rxBytes, txBytes int64, limit *BandwidthPerPeriod, trx *sqlx.Tx) error {
|
func (a *accountWarningAction) HandleAccount(acct *store.Account, rxBytes, txBytes int64, limit *BandwidthPerPeriod, trx *sqlx.Tx) error {
|
||||||
logrus.Infof("warning '%v'", acct.Email)
|
logrus.Infof("warning '%v'", acct.Email)
|
||||||
|
|
||||||
|
if err := sendLimitWarningEmail(a.cfg, acct.Email, limit, rxBytes, txBytes); err != nil {
|
||||||
|
return errors.Wrapf(err, "error sending limit warning email to '%v'", acct.Email)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package limits
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/openziti/zrok/controller/emailUi"
|
||||||
"github.com/openziti/zrok/controller/metrics"
|
"github.com/openziti/zrok/controller/metrics"
|
||||||
"github.com/openziti/zrok/controller/store"
|
"github.com/openziti/zrok/controller/store"
|
||||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||||
@ -31,7 +32,7 @@ type Agent struct {
|
|||||||
join chan struct{}
|
join chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAgent(cfg *Config, ifxCfg *metrics.InfluxConfig, zCfg *zrokEdgeSdk.Config, str *store.Store) (*Agent, error) {
|
func NewAgent(cfg *Config, ifxCfg *metrics.InfluxConfig, zCfg *zrokEdgeSdk.Config, emailCfg *emailUi.Config, str *store.Store) (*Agent, error) {
|
||||||
edge, err := zrokEdgeSdk.Client(zCfg)
|
edge, err := zrokEdgeSdk.Client(zCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -42,13 +43,13 @@ func NewAgent(cfg *Config, ifxCfg *metrics.InfluxConfig, zCfg *zrokEdgeSdk.Confi
|
|||||||
zCfg: zCfg,
|
zCfg: zCfg,
|
||||||
str: str,
|
str: str,
|
||||||
queue: make(chan *metrics.Usage, 1024),
|
queue: make(chan *metrics.Usage, 1024),
|
||||||
acctWarningActions: []AccountAction{newAccountWarningAction(str, edge)},
|
acctWarningActions: []AccountAction{newAccountWarningAction(emailCfg, str, edge)},
|
||||||
acctLimitActions: []AccountAction{newAccountLimitAction(str, edge)},
|
acctLimitActions: []AccountAction{newAccountLimitAction(str, edge)},
|
||||||
acctRelaxActions: []AccountAction{newAccountRelaxAction(str, edge)},
|
acctRelaxActions: []AccountAction{newAccountRelaxAction(str, edge)},
|
||||||
envWarningActions: []EnvironmentAction{newEnvironmentWarningAction(str, edge)},
|
envWarningActions: []EnvironmentAction{newEnvironmentWarningAction(emailCfg, str, edge)},
|
||||||
envLimitActions: []EnvironmentAction{newEnvironmentLimitAction(str, edge)},
|
envLimitActions: []EnvironmentAction{newEnvironmentLimitAction(str, edge)},
|
||||||
envRelaxActions: []EnvironmentAction{newEnvironmentRelaxAction(str, edge)},
|
envRelaxActions: []EnvironmentAction{newEnvironmentRelaxAction(str, edge)},
|
||||||
shrWarningActions: []ShareAction{newShareWarningAction(str, edge)},
|
shrWarningActions: []ShareAction{newShareWarningAction(emailCfg, str, edge)},
|
||||||
shrLimitActions: []ShareAction{newShareLimitAction(str, edge)},
|
shrLimitActions: []ShareAction{newShareLimitAction(str, edge)},
|
||||||
shrRelaxActions: []ShareAction{newShareRelaxAction(str, edge)},
|
shrRelaxActions: []ShareAction{newShareRelaxAction(str, edge)},
|
||||||
close: make(chan struct{}),
|
close: make(chan struct{}),
|
||||||
@ -550,7 +551,7 @@ func (a *Agent) checkShareLimit(shrToken string) (enforce, warning bool, rxBytes
|
|||||||
|
|
||||||
enforce, warning = a.checkLimit(limit, rx, tx)
|
enforce, warning = a.checkLimit(limit, rx, tx)
|
||||||
if enforce || warning {
|
if enforce || warning {
|
||||||
logrus.Debugf("'%v': %v", shrToken, a.describeLimit(limit, rx, tx))
|
logrus.Debugf("'%v': %v", shrToken, describeLimit(limit, rx, tx))
|
||||||
}
|
}
|
||||||
|
|
||||||
return enforce, warning, rx, tx, nil
|
return enforce, warning, rx, tx, nil
|
||||||
@ -580,7 +581,7 @@ func (a *Agent) checkLimit(cfg *BandwidthPerPeriod, rx, tx int64) (enforce, warn
|
|||||||
return false, false
|
return false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) describeLimit(cfg *BandwidthPerPeriod, rx, tx int64) string {
|
func describeLimit(cfg *BandwidthPerPeriod, rx, tx int64) string {
|
||||||
out := ""
|
out := ""
|
||||||
|
|
||||||
if cfg.Limit.Rx != Unlimited && rx > cfg.Limit.Rx {
|
if cfg.Limit.Rx != Unlimited && rx > cfg.Limit.Rx {
|
||||||
|
58
controller/limits/email.go
Normal file
58
controller/limits/email.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package limits
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/openziti/zrok/controller/emailUi"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/wneessen/go-mail"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sendLimitWarningEmail(cfg *emailUi.Config, emailTo string, limit *BandwidthPerPeriod, rxBytes, txBytes int64) error {
|
||||||
|
emailData := &emailUi.WarningEmail{
|
||||||
|
EmailAddress: emailTo,
|
||||||
|
Detail: describeLimit(limit, rxBytes, txBytes),
|
||||||
|
}
|
||||||
|
|
||||||
|
plainBody, err := emailData.MergeTemplate("limitWarning.gotext")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
htmlBody, err := emailData.MergeTemplate("resetPassword.gohtml")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := mail.NewMsg()
|
||||||
|
if err := msg.From(cfg.From); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to set from address in limit warning email")
|
||||||
|
}
|
||||||
|
if err := msg.To(emailTo); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to set to address in limit warning email")
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Subject("Limit Warning Notification")
|
||||||
|
msg.SetDate()
|
||||||
|
msg.SetMessageID()
|
||||||
|
msg.SetBulk()
|
||||||
|
msg.SetImportance(mail.ImportanceHigh)
|
||||||
|
msg.SetBodyString(mail.TypeTextPlain, plainBody)
|
||||||
|
msg.SetBodyString(mail.TypeTextHTML, htmlBody)
|
||||||
|
|
||||||
|
client, err := mail.NewClient(cfg.Host,
|
||||||
|
mail.WithPort(cfg.Port),
|
||||||
|
mail.WithSMTPAuth(mail.SMTPAuthPlain),
|
||||||
|
mail.WithUsername(cfg.Username),
|
||||||
|
mail.WithPassword(cfg.Password),
|
||||||
|
mail.WithTLSPolicy(mail.TLSMandatory),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error creating limit warning email client")
|
||||||
|
}
|
||||||
|
if err := client.DialAndSend(msg); err != nil {
|
||||||
|
return errors.Wrap(err, "error sending limit warning email")
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Infof("limit warning email sent to '%v'", emailTo)
|
||||||
|
return nil
|
||||||
|
}
|
@ -3,20 +3,35 @@ package limits
|
|||||||
import (
|
import (
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/openziti/edge/rest_management_api_client"
|
"github.com/openziti/edge/rest_management_api_client"
|
||||||
|
"github.com/openziti/zrok/controller/emailUi"
|
||||||
"github.com/openziti/zrok/controller/store"
|
"github.com/openziti/zrok/controller/store"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type environmentWarningAction struct {
|
type environmentWarningAction struct {
|
||||||
str *store.Store
|
str *store.Store
|
||||||
edge *rest_management_api_client.ZitiEdgeManagement
|
edge *rest_management_api_client.ZitiEdgeManagement
|
||||||
|
cfg *emailUi.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEnvironmentWarningAction(str *store.Store, edge *rest_management_api_client.ZitiEdgeManagement) *environmentWarningAction {
|
func newEnvironmentWarningAction(cfg *emailUi.Config, str *store.Store, edge *rest_management_api_client.ZitiEdgeManagement) *environmentWarningAction {
|
||||||
return &environmentWarningAction{str, edge}
|
return &environmentWarningAction{str, edge, cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *environmentWarningAction) HandleEnvironment(env *store.Environment, rxBytes, txBytes int64, limit *BandwidthPerPeriod, trx *sqlx.Tx) error {
|
||||||
|
logrus.Infof("warning '%v'", env.ZId)
|
||||||
|
|
||||||
|
if env.AccountId != nil {
|
||||||
|
acct, err := a.str.GetAccount(*env.AccountId, trx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sendLimitWarningEmail(a.cfg, acct.Email, limit, rxBytes, txBytes); err != nil {
|
||||||
|
return errors.Wrapf(err, "error sending limit warning email to '%v'", acct.Email)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *environmentWarningAction) HandleEnvironment(e *store.Environment, rxBytes, txBytes int64, limit *BandwidthPerPeriod, trx *sqlx.Tx) error {
|
|
||||||
logrus.Infof("warning '%v'", e.ZId)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,38 @@ package limits
|
|||||||
import (
|
import (
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/openziti/edge/rest_management_api_client"
|
"github.com/openziti/edge/rest_management_api_client"
|
||||||
|
"github.com/openziti/zrok/controller/emailUi"
|
||||||
"github.com/openziti/zrok/controller/store"
|
"github.com/openziti/zrok/controller/store"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type shareWarningAction struct {
|
type shareWarningAction struct {
|
||||||
str *store.Store
|
str *store.Store
|
||||||
edge *rest_management_api_client.ZitiEdgeManagement
|
edge *rest_management_api_client.ZitiEdgeManagement
|
||||||
|
cfg *emailUi.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func newShareWarningAction(str *store.Store, edge *rest_management_api_client.ZitiEdgeManagement) *shareWarningAction {
|
func newShareWarningAction(cfg *emailUi.Config, str *store.Store, edge *rest_management_api_client.ZitiEdgeManagement) *shareWarningAction {
|
||||||
return &shareWarningAction{str, edge}
|
return &shareWarningAction{str, edge, cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *shareWarningAction) HandleShare(shr *store.Share, rxBytes, txBytes int64, limit *BandwidthPerPeriod, trx *sqlx.Tx) error {
|
||||||
|
logrus.Infof("warning '%v'", shr.Token)
|
||||||
|
|
||||||
|
env, err := a.str.GetEnvironment(shr.EnvironmentId, trx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
acct, err := a.str.GetAccount(env.Id, trx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sendLimitWarningEmail(a.cfg, acct.Email, limit, rxBytes, txBytes); err != nil {
|
||||||
|
return errors.Wrapf(err, "error sending limit warning email to '%v'", acct.Email)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *shareWarningAction) HandleShare(s *store.Share, rxBytes, txBytes int64, limit *BandwidthPerPeriod, trx *sqlx.Tx) error {
|
|
||||||
logrus.Infof("warning '%v'", s.Token)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user