diff --git a/README.md b/README.md index 3cc16dac..d47b8214 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ See also: - ignored IP Address - error occurred - configurable retries and delay between retries - - hard-coded notifications rate limit in order to respect remote API limits + - configurable notifications rate limit (used to respect remote API limits) - Logging - Payload receipt from monitoring system diff --git a/cmd/brick/notify.go b/cmd/brick/notify.go index c559a871..bef66f8f 100644 --- a/cmd/brick/notify.go +++ b/cmd/brick/notify.go @@ -630,7 +630,7 @@ func NotifyMgr(ctx context.Context, cfg *config.Config, notifyWorkQueue <-chan e ctx, cfg.TeamsWebhookURL(), config.NotifyMgrTeamsNotificationTimeout, - config.NotifyMgrTeamsNotificationRateLimit, + cfg.TeamsNotificationRateLimit(), cfg.TeamsNotificationRetries(), cfg.TeamsNotificationRetryDelay(), teamsNotifyWorkQueue, @@ -647,7 +647,7 @@ func NotifyMgr(ctx context.Context, cfg *config.Config, notifyWorkQueue <-chan e go emailNotifier( ctx, config.NotifyMgrEmailNotificationTimeout, - config.NotifyMgrEmailNotificationRateLimit, + cfg.EmailNotificationRateLimit(), cfg.EmailNotificationRetries(), cfg.EmailNotificationRetryDelay(), emailNotifyWorkQueue, diff --git a/config/constants.go b/config/constants.go index f6800d62..e84246b1 100644 --- a/config/constants.go +++ b/config/constants.go @@ -63,6 +63,13 @@ const ( // No assumptions can be safely made here; user has to supply this defaultMSTeamsWebhookURL string = "" + // the number of seconds to wait between Microsoft Teams notification + // attempts. This rate limit is intended to help prevent unintentional + // abuse of remote services and is applied regardless of whether the last + // notification attempt was initially successful or required one or more + // retry attempts. + defaultMSTeamsRateLimit int = 5 + // the number of attempts to deliver messages before giving up; applies to // Microsoft Teams notifications only defaultMSTeamsRetries int = 2 @@ -144,16 +151,6 @@ const ( // more often than this duration. This limiter is to keep from logging the // details so often that the information simply becomes noise. NotifyQueueMonitorDelay time.Duration = 15 * time.Second - - // NotifyMgrTeamsNotificationRateLimit is the rate limit between Microsoft - // Teams notification attempts. This limit is intended to help prevent - // unintentional abuse of remote services. - NotifyMgrTeamsNotificationRateLimit time.Duration = 5 * time.Second - - // NotifyMgrEmailNotificationRateLimit is the rate limit between email - // notification attempts. This limit is intended to help prevent - // unintentional abuse of remote services. - NotifyMgrEmailNotificationRateLimit time.Duration = 5 * time.Second ) // NotifyMgrQueueDepth is the number of items allowed into the queue/channel diff --git a/config/getters.go b/config/getters.go index ce04643e..f3adec9d 100644 --- a/config/getters.go +++ b/config/getters.go @@ -18,6 +18,7 @@ package config import ( "os" + "time" "github.com/apex/log" ) @@ -286,6 +287,24 @@ func (c Config) TeamsWebhookURL() string { } } +// TeamsNotificationRateLimit returns a time.Duration value based on the +// user-provided rate limit in seconds between Microsoft Teams notifications +// or the default value if not provided. CLI flag values take precedence if +// provided. +func (c Config) TeamsNotificationRateLimit() time.Duration { + var rateLimitSeconds int + switch { + case c.cliConfig.MSTeams.RateLimit != nil: + rateLimitSeconds = *c.cliConfig.MSTeams.RateLimit + case c.fileConfig.MSTeams.RateLimit != nil: + rateLimitSeconds = *c.fileConfig.MSTeams.RateLimit + default: + rateLimitSeconds = defaultMSTeamsRateLimit + } + + return time.Duration(rateLimitSeconds) * time.Second +} + // TeamsNotificationRetries returns the user-provided retry limit before // giving up on message delivery or the default value if not provided. CLI // flag values take precedence if provided. @@ -343,6 +362,26 @@ func (c Config) NotifyEmail() bool { } +// EmailNotificationRateLimit returns a time.Duration value based on the +// user-provided rate limit in seconds between email notifications or the +// default value if not provided. CLI flag values take precedence if provided. +func (c Config) EmailNotificationRateLimit() time.Duration { + var rateLimitSeconds int + // switch { + // case c.cliConfig.Email.RateLimit != nil: + // rateLimitSeconds = *c.cliConfig.MSTeams.RateLimit + // case c.fileConfig.MSTeams.RateLimit != nil: + // rateLimitSeconds = *c.fileConfig.MSTeams.RateLimit + // default: + // rateLimitSeconds = defaultMSTeamsRateLimit + // } + + log.Warn("FIXME: Placeholder value until GH-3 is implemented") + rateLimitSeconds = 5 + + return time.Duration(rateLimitSeconds) * time.Second +} + // EmailNotificationRetries returns the user-provided retry limit before // giving up on email message delivery or the default value if not provided. // CLI flag values take precedence if provided. diff --git a/config/types.go b/config/types.go index 1a4c78ad..dbd331b5 100644 --- a/config/types.go +++ b/config/types.go @@ -138,6 +138,13 @@ type MSTeams struct { // application. WebhookURL *string `toml:"webhook_url" arg:"--teams-webhook-url,env:BRICK_MSTEAMS_WEBHOOK_URL" help:"The Webhook URL provided by a preconfigured Connector. If specified, this application will attempt to send client request details to the Microsoft Teams channel associated with the webhook URL."` + // RateLimit is the number of seconds to wait between Microsoft Teams + // notification attempts. This rate limit is intended to help prevent + // unintentional abuse of remote services and is applied regardless of + // whether the last notification attempt was initially successful or + // required one or more retry attempts. + RateLimit *int `toml:"rate_limit" arg:"--teams-notify-rate-limit,env:BRICK_MSTEAMS_WEBHOOK_RATE_LIMIT" help:"The number of seconds to wait between Microsoft Teams notification attempts. This rate limit is intended to help prevent unintentional abuse of remote services and is applied regardless of whether the last notification attempt was initially successful or required one or more retry attempts."` + // RetryDelay is the number of seconds to wait between Microsoft Teams // message delivery retry attempts. RetryDelay *int `toml:"retry_delay" arg:"--teams-notify-retry-delay,env:BRICK_MSTEAMS_WEBHOOK_RETRY_DELAY" help:"The number of seconds to wait between Microsoft Teams message delivery retry attempts."` diff --git a/config/validate.go b/config/validate.go index c9530b69..4a167655 100644 --- a/config/validate.go +++ b/config/validate.go @@ -153,6 +153,14 @@ func validate(c Config) error { } + if c.TeamsNotificationRateLimit() < 0 { + log.Debugf("unsupported rate limit specified for MS Teams notifications: %d ", c.TeamsNotificationRateLimit()) + return fmt.Errorf( + "invalid rate limit specified for MS Teams notifications: %d", + c.TeamsNotificationRateLimit(), + ) + } + if c.TeamsNotificationRetryDelay() < 0 { log.Debugf("unsupported retry delay specified for MS Teams notifications: %d ", c.TeamsNotificationRetryDelay()) return fmt.Errorf( diff --git a/contrib/brick/config.example.toml b/contrib/brick/config.example.toml index a94c66e3..a23715e2 100644 --- a/contrib/brick/config.example.toml +++ b/contrib/brick/config.example.toml @@ -115,6 +115,12 @@ file_path = "/usr/local/etc/brick/ips.brick-ignored.txt" # using this application. webhook_url = "" +# The number of seconds to wait between Microsoft Teams notification attempts. +# This rate limit is intended to help prevent unintentional abuse of remote +# services and is applied regardless of whether the last notification attempt +# was initially successful or required one or more retry attempts. +rate_limit = 5 + # The number of attempts that this application will make to deliver Microsoft # Teams messages before giving up. retries = 2 diff --git a/doc.go b/doc.go index da9dccf4..22f5a640 100644 --- a/doc.go +++ b/doc.go @@ -54,7 +54,7 @@ FEATURES • User configurable support for ignoring specific IP Addresses (i.e., prevent disabling associated account) -• Microsoft Teams notifications generated for multiple events with configurable retries and notification retry delay +• Microsoft Teams notifications generated for multiple events with configurable rate limit, notification retries, and retry delay • Logging of all events (e.g., payload receipt, action taken due to payload) diff --git a/docs/configure.md b/docs/configure.md index 1f730faa..1a65b721 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -51,6 +51,7 @@ environment variables) and use the configuration file for the other settings. | `ignored-users-file` | No | `/usr/local/etc/brick/users.brick-ignored.txt` | No | *valid path to a file* | Fully-qualified path to the file containing a list of user accounts which should not be disabled and whose IP Address reported in the same alert should not be banned by this application. Leading and trailing whitespace per line is ignored. | | `ignored-ips-file` | No | `/usr/local/etc/brick/ips.brick-ignored.txt` | No | *valid path to a file* | Fully-qualified path to the file containing a list of individual IP Addresses which should not be disabled and whose user account reported in the same alert should not be disabled by this application. Leading and trailing whitespace per line is ignored. | | `teams-webhook-url` | No | *empty string* | No | [*valid webhook url*](#worth-noting) | The Webhook URL provided by a preconfigured Connector. If specified, this application will attempt to send client request details to the Microsoft Teams channel associated with the webhook URL. | +| `teams-notify-rate-limit` | No | `5` | No | *number of seconds as a whole number* | The number of seconds to wait between Microsoft Teams notification attempts. This rate limit is intended to help prevent unintentional abuse of remote services and is applied regardless of whether the last notification attempt was initially successful or required one or more retry attempts. | | `teams-notify-retry-delay` | No | `5` | No | *valid whole number* | The number of seconds to wait between Microsoft Teams message retry delivery attempts. | | `teams-notify-retries` | No | `2` | No | *valid whole number* | The number of attempts that this application will make to deliver Microsoft Teams messages before giving up. | | `ezproxy-executable-path` | No | `/usr/local/ezproxy/ezproxy` | No | *valid path to a file* | The fully-qualified path to the EZproxy executable/binary. This executable is usually named 'ezproxy' and is set to start at system boot. The fully-qualified path to this executable is required for session termination. | @@ -84,6 +85,7 @@ Arguments](#command-line-arguments) table for more information. | `ignored-users-file` | `BRICK_IGNORED_USERS_FILE` | | `BRICK_IGNORED_USERS_FILE="/usr/local/etc/brick/users.brick-ignored.txt"` | | `ignored-ips-file` | `BRICK_IGNORED_IP_ADDRESSES_FILE` | | `BRICK_IGNORED_IP_ADDRESSES_FILE="/usr/local/etc/brick/ips.brick-ignored.txt"` | | `teams-webhook-url` | `BRICK_MSTEAMS_WEBHOOK_URL` | | `BRICK_MSTEAMS_WEBHOOK_URL="https://outlook.office.com/webhook/a1269812-6d10-44b1-abc5-b84f93580ba0@9e7b80c7-d1eb-4b52-8582-76f921e416d9/IncomingWebhook/3fdd6767bae44ac58e5995547d66a4e4/f332c8d9-3397-4ac5-957b-b8e3fc465a8c"` | +| `teams-notify-rate-limit` | `BRICK_MSTEAMS_WEBHOOK_RATE_LIMIT` | | `BRICK_MSTEAMS_WEBHOOK_RATE_LIMIT=5` | | `teams-notify-retry-delay` | `BRICK_MSTEAMS_WEBHOOK_RETRY_DELAY` | | `BRICK_MSTEAMS_WEBHOOK_RETRY_DELAY="2"` | | `teams-notify-retries` | `BRICK_MSTEAMS_WEBHOOK_RETRIES` | | `BRICK_MSTEAMS_WEBHOOK_RETRIES="5"` | | `ezproxy-executable-path` | `BRICK_EZPROXY_EXECUTABLE_PATH` | | `BRICK_EZPROXY_EXECUTABLE_PATH="/usr/local/ezproxy/ezproxy"` | @@ -117,6 +119,7 @@ settings. | `ignored-users-file` | `file_path` | `ignoredusers` | | | `ignored-ips-file` | `file_path` | `ignoredipaddresses` | | | `teams-webhook-url` | `webhook_url` | `msteams` | | +| `teams-notify-rate-limit` | `rate_limit` | `msteams` | | | `teams-notify-retry-delay` | `retry_delay` | `msteams` | | | `teams-notify-retries` | `retries` | `msteams` | | | `ezproxy-executable-path` | `executable_path` | `ezproxy` | |