Skip to content

Commit

Permalink
eventstream: move config parsing out of main to package
Browse files Browse the repository at this point in the history
Next to moving the configuration parsing code from the main file to the
eventstream package, the custom TLS configuration creation was changed
to allow multiple (possible future) configuration options.
  • Loading branch information
oxzi committed Oct 23, 2023
1 parent 75e6337 commit bcbbbc8
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 41 deletions.
46 changes: 5 additions & 41 deletions cmd/icinga-notifications-daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package main

import (
"context"
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"github.com/icinga/icinga-notifications/internal"
Expand All @@ -13,7 +11,6 @@ import (
"github.com/icinga/icingadb/pkg/logging"
"github.com/icinga/icingadb/pkg/utils"
"go.uber.org/zap"
"net/http"
"os"
"os/signal"
"runtime"
Expand Down Expand Up @@ -88,44 +85,11 @@ func main() {

go runtimeConfig.PeriodicUpdates(ctx, 1*time.Second)

for _, icinga2Api := range conf.Icinga2Apis {
logger := logs.GetChildLogger(fmt.Sprintf("eventstream-%d", icinga2Api.NotificationsEventSourceId))

esClient := eventstream.Client{
ApiHost: icinga2Api.Host,
ApiBasicAuthUser: icinga2Api.AuthUser,
ApiBasicAuthPass: icinga2Api.AuthPass,

IcingaNotificationsEventSourceId: icinga2Api.NotificationsEventSourceId,
IcingaWebRoot: conf.Icingaweb2URL,

CallbackFn: eventstream.MakeProcessEvent(db, logger, logs, runtimeConfig, conf),
Ctx: ctx,
Logger: logger,
}

switch {
case icinga2Api.IcingaCaFile != "":
caData, err := os.ReadFile(icinga2Api.IcingaCaFile)
if err != nil {
logger.Errorw("Cannot read CA file", zap.String("file", icinga2Api.IcingaCaFile), zap.Error(err))
continue
}

certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caData) {
logger.Error("Cannot add CA file to cert pool")
continue
}

esClient.ApiHttpTransport = http.Transport{TLSClientConfig: &tls.Config{RootCAs: certPool}}
logger.Debug("Configured custom CA file for API HTTPS requests")

case icinga2Api.InsecureTls:
esClient.ApiHttpTransport = http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
logger.Warn("Skipping TLS verification for API HTTPS requests")
}

esClients, err := eventstream.NewClientsFromConfig(ctx, logs, db, runtimeConfig, conf)
if err != nil {
logger.Fatalw("cannot prepare Event Stream API Clients form config", zap.Error(err))
}
for _, esClient := range esClients {
go esClient.Process()
}

Expand Down
64 changes: 64 additions & 0 deletions internal/eventstream/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ package eventstream

import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"github.com/icinga/icinga-notifications/internal/config"
"github.com/icinga/icinga-notifications/internal/event"
"github.com/icinga/icingadb/pkg/icingadb"
"github.com/icinga/icingadb/pkg/logging"
"hash/fnv"
"net/http"
"net/url"
"os"
"slices"
"sync"
"time"
Expand Down Expand Up @@ -43,6 +49,64 @@ type Client struct {
eventsLastTs time.Time
}

// NewClientsFromConfig returns all Clients defined in the conf.ConfigFile.
//
// Those are prepared and just needed to be started by calling their Process method.
func NewClientsFromConfig(
ctx context.Context,
logs *logging.Logging,
db *icingadb.DB,
runtimeConfig *config.RuntimeConfig,
conf *config.ConfigFile,
) ([]*Client, error) {
clients := make([]*Client, 0, len(conf.Icinga2Apis))

for _, icinga2Api := range conf.Icinga2Apis {
logger := logs.GetChildLogger(fmt.Sprintf("eventstream-%d", icinga2Api.NotificationsEventSourceId))

client := &Client{
ApiHost: icinga2Api.Host,
ApiBasicAuthUser: icinga2Api.AuthUser,
ApiBasicAuthPass: icinga2Api.AuthPass,
ApiHttpTransport: http.Transport{
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS13,
},
},

IcingaNotificationsEventSourceId: icinga2Api.NotificationsEventSourceId,
IcingaWebRoot: conf.Icingaweb2URL,

CallbackFn: MakeProcessEvent(db, logger, logs, runtimeConfig, conf),
Ctx: ctx,
Logger: logger,
}

if icinga2Api.IcingaCaFile != "" {
caData, err := os.ReadFile(icinga2Api.IcingaCaFile)
if err != nil {
return nil, fmt.Errorf("cannot read CA file %q for Event Stream ID %d, %w",
icinga2Api.IcingaCaFile, icinga2Api.NotificationsEventSourceId, err)
}

certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caData) {
return nil, fmt.Errorf("cannot add custom CA file to CA pool for Event Stream ID %d, %w",
icinga2Api.NotificationsEventSourceId, err)
}

client.ApiHttpTransport.TLSClientConfig.RootCAs = certPool
}

if icinga2Api.InsecureTls {
client.ApiHttpTransport.TLSClientConfig.InsecureSkipVerify = true
}

clients = append(clients, client)
}
return clients, nil
}

// buildCommonEvent creates an event.Event based on Host and (optional) Service attributes to be specified later.
//
// The following fields will NOT be populated and might be altered later:
Expand Down

0 comments on commit bcbbbc8

Please sign in to comment.