Skip to content

Commit

Permalink
periodically fix missing or modified rules
Browse files Browse the repository at this point in the history
  • Loading branch information
capnspacehook committed Sep 10, 2023
1 parent 7edd372 commit 613df15
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 9 deletions.
8 changes: 7 additions & 1 deletion cmd/whalewall/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func mainRetCode() int {
debugLogs := flag.Bool("debug", false, "enable debug logging")
logPath := flag.String("l", "stdout", "path to log to")
timeout := flag.Duration("t", 10*time.Second, "timeout for Docker API requests")
watchInterval := flag.Duration("i", time.Minute, "interval to check created container rules")
displayVersion := flag.Bool("version", false, "print version and build information and exit")
flag.Parse()

Expand All @@ -49,6 +50,11 @@ func mainRetCode() int {
return 0
}

if *watchInterval <= 0 {
log.Println("-i must be greater than 0")
return 1
}

// build logger
logCfg := zap.NewProductionConfig()
logCfg.OutputPaths = []string{*logPath}
Expand Down Expand Up @@ -92,7 +98,7 @@ func mainRetCode() int {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()

r, err := whalewall.NewRuleManager(ctx, logger, sqliteFile, *timeout)
r, err := whalewall.NewRuleManager(ctx, logger, sqliteFile, *timeout, *watchInterval)
if err != nil {
logger.Error("error initializing", zap.Error(err))
}
Expand Down
6 changes: 5 additions & 1 deletion create.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ func (r *RuleManager) createContainerRules(ctx context.Context, container types.

contName := stripName(container.Name)
logger := r.logger.With(zap.String("container.id", container.ID[:12]), zap.String("container.name", contName))
logger.Info("creating rules", zap.Bool("container.is_new", isNew))
if isNew {
logger.Info("creating rules", zap.Bool("container.is_new", isNew))
} else {
logger.Debug("watching rules", zap.Bool("container.is_new", isNew))
}

// check that network settings are valid
if container.NetworkSettings == nil {
Expand Down
12 changes: 10 additions & 2 deletions manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ type RuleManager struct {

containerTracker *container.Tracker

watchInterval time.Duration

createCh chan containerDetails
deleteCh chan string

Expand All @@ -70,7 +72,7 @@ type containerDetails struct {
isNew bool
}

func NewRuleManager(ctx context.Context, logger *zap.Logger, dbFile string, timeout time.Duration) (*RuleManager, error) {
func NewRuleManager(ctx context.Context, logger *zap.Logger, dbFile string, timeout, watchInterval time.Duration) (*RuleManager, error) {
r := RuleManager{
stopping: make(chan struct{}),
done: make(chan struct{}),
Expand All @@ -89,6 +91,7 @@ func NewRuleManager(ctx context.Context, logger *zap.Logger, dbFile string, time
return nftables.New()
},
containerTracker: container.NewTracker(logger),
watchInterval: watchInterval,
createCh: make(chan containerDetails),
deleteCh: make(chan string),
}
Expand Down Expand Up @@ -126,7 +129,12 @@ func (r *RuleManager) Start(ctx context.Context) error {
r.logger.Error("error syncing containers", zap.Error(err))
}

r.wg.Add(1)
r.wg.Add(2)
go func() {
defer r.wg.Done()

r.watchContainers(ctx)
}()
go func() {
defer r.wg.Done()

Expand Down
35 changes: 35 additions & 0 deletions sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"slices"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
Expand Down Expand Up @@ -74,6 +75,40 @@ func (r *RuleManager) syncContainers(ctx context.Context) error {
return nil
}

// watchContainers periodically checks that container rules created by
// whalewall haven't been deleted, modified or added to and fixes them
// if necessary.
func (r *RuleManager) watchContainers(ctx context.Context) {
ticker := time.NewTicker(r.watchInterval)
defer ticker.Stop()

for {
select {
case <-ticker.C:
conts, err := r.db.GetContainers(ctx)
if err != nil {
r.logger.Error("error getting containers from database", zap.Error(err))
continue
}
for _, c := range conts {
container, err := r.dockerCli.ContainerInspect(ctx, c.ID)
if err != nil {
r.logger.Error("error inspecting container", zap.String("container.id", c.ID[:12]), zap.Error(err))
continue
}
r.createCh <- containerDetails{
container: container,
isNew: false,
}
}
case <-ctx.Done():
return
case <-r.stopping:
return
}
}
}

func whalewallEnabled(labels map[string]string) (bool, error) {
e, ok := labels[enabledLabel]
if !ok {
Expand Down
10 changes: 5 additions & 5 deletions whalewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ func startFunc(t *testing.T, is *is.I, tempDir string) func() {
logger.Info("starting whalewall")
ctx, cancel := context.WithCancel(context.Background())
dbFile := filepath.Join(tempDir, "db.sqlite")
r, err := NewRuleManager(ctx, logger, dbFile, defaultTimeout)
r, err := NewRuleManager(ctx, logger, dbFile, defaultTimeout, time.Minute)
is.NoErr(err)
err = r.Start(ctx)
is.NoErr(err)
Expand Down Expand Up @@ -2335,7 +2335,7 @@ mapped_ports:
is := is.New(t)

dbFile := filepath.Join(t.TempDir(), "db.sqlite")
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout)
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout, defaultTimeout)
is.NoErr(err)

var dockerCli *mockDockerClient
Expand Down Expand Up @@ -2559,7 +2559,7 @@ output:
}

dbFile := filepath.Join(t.TempDir(), "db.sqlite")
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout)
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout, time.Minute)
is.NoErr(err)

dockerCli := newMockDockerClient(nil)
Expand Down Expand Up @@ -2701,7 +2701,7 @@ output:
}

dbFile := filepath.Join(t.TempDir(), "db.sqlite")
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout)
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout, time.Minute)
is.NoErr(err)

dockerCli := newMockDockerClient(nil)
Expand Down Expand Up @@ -2838,7 +2838,7 @@ output:
is.NoErr(err)

dbFile := filepath.Join(t.TempDir(), "db.sqlite")
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout)
r, err := NewRuleManager(context.Background(), logger, dbFile, defaultTimeout, time.Minute)
is.NoErr(err)

// configure database to pause before committing so we can cancel
Expand Down

0 comments on commit 613df15

Please sign in to comment.