1
0
Fork 0
mirror of https://github.com/pomerium/pomerium.git synced 2025-05-17 19:17:17 +02:00
pomerium/internal/zero/bootstrap/source.go
Joe Kralicky fe31799eb5
Fix many instances of contexts and loggers not being propagated ()
This also replaces instances where we manually write "return ctx.Err()"
with "return context.Cause(ctx)" which is functionally identical, but
will also correctly propagate cause errors if present.
2024-10-25 14:50:56 -04:00

103 lines
2.6 KiB
Go

package bootstrap
import (
"context"
"encoding/base64"
"sync"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/atomicutil"
"github.com/pomerium/pomerium/internal/log"
cluster_api "github.com/pomerium/pomerium/pkg/zero/cluster"
)
var _ = config.Source(new(source))
var cmpOpts = []cmp.Option{
cmpopts.IgnoreUnexported(config.Options{}),
cmpopts.EquateEmpty(),
}
type source struct {
cfg atomicutil.Value[*config.Config]
listenerLock sync.RWMutex
listeners []config.ChangeListener
ready chan struct{}
markReady sync.Once
}
func (src *source) WaitReady(ctx context.Context) error {
select {
case <-ctx.Done():
return context.Cause(ctx)
case <-src.ready:
return nil
}
}
// GetConfig implements config.Source
func (src *source) GetConfig() *config.Config {
return src.cfg.Load()
}
// OnConfigChange implements config.Source
func (src *source) OnConfigChange(_ context.Context, l config.ChangeListener) {
src.listenerLock.Lock()
src.listeners = append(src.listeners, l)
src.listenerLock.Unlock()
}
// UpdateBootstrap updates the underlying configuration options
func (src *source) UpdateBootstrap(ctx context.Context, cfg cluster_api.BootstrapConfig) bool {
current := src.cfg.Load()
incoming := current.Clone()
applyBootstrapConfig(incoming, &cfg)
if cmp.Equal(incoming, current, cmpOpts...) {
return false
}
src.cfg.Store(incoming)
src.markReady.Do(func() {
log.Ctx(ctx).Info().
Str("organization-id", cfg.OrganizationId).
Str("cluster-id", cfg.ClusterId).
Msg("loaded Pomerium Zero bootstrap config")
close(src.ready)
})
src.notifyListeners(ctx, incoming)
return true
}
// notifyListeners notifies all listeners of a configuration change
func (src *source) notifyListeners(ctx context.Context, cfg *config.Config) {
src.listenerLock.RLock()
listeners := make([]config.ChangeListener, len(src.listeners))
copy(listeners, src.listeners)
src.listenerLock.RUnlock()
for _, l := range listeners {
l(ctx, cfg)
}
}
func applyBootstrapConfig(dst *config.Config, src *cluster_api.BootstrapConfig) {
dst.Options.SharedKey = base64.StdEncoding.EncodeToString(src.SharedSecret)
if src.DatabrokerStorageConnection != nil {
dst.Options.DataBrokerStorageType = config.StoragePostgresName
dst.Options.DataBrokerStorageConnectionString = *src.DatabrokerStorageConnection
} else {
dst.Options.DataBrokerStorageType = config.StorageInMemoryName
dst.Options.DataBrokerStorageConnectionString = ""
}
dst.ZeroClusterID = src.ClusterId
dst.ZeroOrganizationID = src.OrganizationId
dst.ZeroPseudonymizationKey = src.PseudonymizationKey
}