core/config: add databroker_storage_connection_string_file (#5242)

* core/config: add databroker_storage_connection_string_file

* add file to file list
This commit is contained in:
Caleb Doxsey 2024-08-27 09:42:14 -06:00 committed by GitHub
parent d062f9d68d
commit f3620cf6e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 110 additions and 15 deletions

View file

@ -281,6 +281,7 @@ func getAllConfigFilePaths(cfg *Config) []string {
cfg.Options.CertFile, cfg.Options.CertFile,
cfg.Options.ClientSecretFile, cfg.Options.ClientSecretFile,
cfg.Options.CookieSecretFile, cfg.Options.CookieSecretFile,
cfg.Options.DataBrokerStorageConnectionStringFile,
cfg.Options.DataBrokerStorageCAFile, cfg.Options.DataBrokerStorageCAFile,
cfg.Options.DataBrokerStorageCertFile, cfg.Options.DataBrokerStorageCertFile,
cfg.Options.DataBrokerStorageCertKeyFile, cfg.Options.DataBrokerStorageCertKeyFile,

View file

@ -249,11 +249,12 @@ type Options struct {
// Supported type: memory, postgres // Supported type: memory, postgres
DataBrokerStorageType string `mapstructure:"databroker_storage_type" yaml:"databroker_storage_type,omitempty"` DataBrokerStorageType string `mapstructure:"databroker_storage_type" yaml:"databroker_storage_type,omitempty"`
// DataBrokerStorageConnectionString is the data source name for storage backend. // DataBrokerStorageConnectionString is the data source name for storage backend.
DataBrokerStorageConnectionString string `mapstructure:"databroker_storage_connection_string" yaml:"databroker_storage_connection_string,omitempty"` DataBrokerStorageConnectionString string `mapstructure:"databroker_storage_connection_string" yaml:"databroker_storage_connection_string,omitempty"`
DataBrokerStorageCertFile string `mapstructure:"databroker_storage_cert_file" yaml:"databroker_storage_cert_file,omitempty"` DataBrokerStorageConnectionStringFile string `mapstructure:"databroker_storage_connection_string_file" yaml:"databroker_storage_connection_string_file,omitempty"`
DataBrokerStorageCertKeyFile string `mapstructure:"databroker_storage_key_file" yaml:"databroker_storage_key_file,omitempty"` DataBrokerStorageCertFile string `mapstructure:"databroker_storage_cert_file" yaml:"databroker_storage_cert_file,omitempty"`
DataBrokerStorageCAFile string `mapstructure:"databroker_storage_ca_file" yaml:"databroker_storage_ca_file,omitempty"` DataBrokerStorageCertKeyFile string `mapstructure:"databroker_storage_key_file" yaml:"databroker_storage_key_file,omitempty"`
DataBrokerStorageCertSkipVerify bool `mapstructure:"databroker_storage_tls_skip_verify" yaml:"databroker_storage_tls_skip_verify,omitempty"` DataBrokerStorageCAFile string `mapstructure:"databroker_storage_ca_file" yaml:"databroker_storage_ca_file,omitempty"`
DataBrokerStorageCertSkipVerify bool `mapstructure:"databroker_storage_tls_skip_verify" yaml:"databroker_storage_tls_skip_verify,omitempty"`
// DownstreamMTLS holds all downstream mTLS settings. // DownstreamMTLS holds all downstream mTLS settings.
DownstreamMTLS DownstreamMTLSSettings `mapstructure:"downstream_mtls" yaml:"downstream_mtls,omitempty"` DownstreamMTLS DownstreamMTLSSettings `mapstructure:"downstream_mtls" yaml:"downstream_mtls,omitempty"`
@ -592,7 +593,7 @@ func (o *Options) Validate() error {
switch o.DataBrokerStorageType { switch o.DataBrokerStorageType {
case StorageInMemoryName: case StorageInMemoryName:
case StoragePostgresName: case StoragePostgresName:
if o.DataBrokerStorageConnectionString == "" { if o.DataBrokerStorageConnectionString == "" && o.DataBrokerStorageConnectionStringFile == "" {
return errors.New("config: missing databroker storage backend dsn") return errors.New("config: missing databroker storage backend dsn")
} }
default: default:
@ -1084,6 +1085,17 @@ func (o *Options) GetDataBrokerCertificate() (*tls.Certificate, error) {
return cryptutil.CertificateFromFile(o.DataBrokerStorageCertFile, o.DataBrokerStorageCertKeyFile) return cryptutil.CertificateFromFile(o.DataBrokerStorageCertFile, o.DataBrokerStorageCertKeyFile)
} }
// GetDataBrokerStorageConnectionString gets the databroker storage connection string from either a file
// or the config option directly. If from a file spaces are trimmed off the ends.
func (o *Options) GetDataBrokerStorageConnectionString() (string, error) {
if o.DataBrokerStorageConnectionStringFile != "" {
bs, err := os.ReadFile(o.DataBrokerStorageConnectionStringFile)
return strings.TrimSpace(string(bs)), err
}
return o.DataBrokerStorageConnectionString, nil
}
// GetCertificates gets all the certificates from the options. // GetCertificates gets all the certificates from the options.
func (o *Options) GetCertificates() ([]tls.Certificate, error) { func (o *Options) GetCertificates() ([]tls.Certificate, error) {
var certs []tls.Certificate var certs []tls.Certificate

View file

@ -1300,6 +1300,66 @@ func TestOptions_RuntimeFlags(t *testing.T) {
} }
} }
func TestOptions_GetDataBrokerStorageConnectionString(t *testing.T) {
t.Parallel()
t.Run("validate", func(t *testing.T) {
t.Parallel()
o := NewDefaultOptions()
o.Services = "databroker"
o.DataBrokerStorageType = "postgres"
o.SharedKey = cryptutil.NewBase64Key()
assert.ErrorContains(t, o.Validate(), "missing databroker storage backend dsn",
"should validate DSN")
o.DataBrokerStorageConnectionString = "DSN"
assert.NoError(t, o.Validate(),
"should have no error when the dsn is set")
o.DataBrokerStorageConnectionString = ""
o.DataBrokerStorageConnectionStringFile = "DSN_FILE"
assert.NoError(t, o.Validate(),
"should have no error when the dsn file is set")
})
t.Run("literal", func(t *testing.T) {
t.Parallel()
o := NewDefaultOptions()
o.DataBrokerStorageConnectionString = "DSN"
dsn, err := o.GetDataBrokerStorageConnectionString()
assert.NoError(t, err)
assert.Equal(t, "DSN", dsn)
})
t.Run("file", func(t *testing.T) {
t.Parallel()
dir := t.TempDir()
fp := filepath.Join(dir, "DSN_FILE")
o := NewDefaultOptions()
o.DataBrokerStorageConnectionStringFile = fp
o.DataBrokerStorageConnectionString = "IGNORED"
dsn, err := o.GetDataBrokerStorageConnectionString()
assert.Error(t, err,
"should return an error when the file doesn't exist")
assert.Empty(t, dsn)
os.WriteFile(fp, []byte(`
DSN
`), 0o644)
dsn, err = o.GetDataBrokerStorageConnectionString()
assert.NoError(t, err,
"should not return an error when the file exists")
assert.Equal(t, "DSN", dsn,
"should return the trimmed contents of the file")
})
}
func encodeCert(cert *tls.Certificate) []byte { func encodeCert(cert *tls.Certificate) []byte {
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Certificate[0]}) return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Certificate[0]})
} }

View file

@ -91,7 +91,10 @@ func New(cfg *config.Config, eventsMgr *events.Manager) (*DataBroker, error) {
return nil, err return nil, err
} }
dataBrokerServer := newDataBrokerServer(cfg) dataBrokerServer, err := newDataBrokerServer(cfg)
if err != nil {
return nil, err
}
c := &DataBroker{ c := &DataBroker{
dataBrokerServer: dataBrokerServer, dataBrokerServer: dataBrokerServer,

View file

@ -3,12 +3,14 @@ package databroker
import ( import (
"context" "context"
"fmt"
"google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb"
"github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/atomicutil" "github.com/pomerium/pomerium/internal/atomicutil"
"github.com/pomerium/pomerium/internal/databroker" "github.com/pomerium/pomerium/internal/databroker"
"github.com/pomerium/pomerium/internal/log"
databrokerpb "github.com/pomerium/pomerium/pkg/grpc/databroker" databrokerpb "github.com/pomerium/pomerium/pkg/grpc/databroker"
registrypb "github.com/pomerium/pomerium/pkg/grpc/registry" registrypb "github.com/pomerium/pomerium/pkg/grpc/registry"
"github.com/pomerium/pomerium/pkg/grpcutil" "github.com/pomerium/pomerium/pkg/grpcutil"
@ -21,31 +23,48 @@ type dataBrokerServer struct {
} }
// newDataBrokerServer creates a new databroker service server. // newDataBrokerServer creates a new databroker service server.
func newDataBrokerServer(cfg *config.Config) *dataBrokerServer { func newDataBrokerServer(cfg *config.Config) (*dataBrokerServer, error) {
srv := &dataBrokerServer{ srv := &dataBrokerServer{
sharedKey: atomicutil.NewValue([]byte{}), sharedKey: atomicutil.NewValue([]byte{}),
} }
srv.server = databroker.New(srv.getOptions(cfg)...)
opts, err := srv.getOptions(cfg)
if err != nil {
return nil, err
}
srv.server = databroker.New(opts...)
srv.setKey(cfg) srv.setKey(cfg)
return srv return srv, nil
} }
// OnConfigChange updates the underlying databroker server whenever configuration is changed. // OnConfigChange updates the underlying databroker server whenever configuration is changed.
func (srv *dataBrokerServer) OnConfigChange(_ context.Context, cfg *config.Config) { func (srv *dataBrokerServer) OnConfigChange(ctx context.Context, cfg *config.Config) {
srv.server.UpdateConfig(srv.getOptions(cfg)...) opts, err := srv.getOptions(cfg)
if err != nil {
log.Error(ctx).Err(err).Msg("databroker: error updating config changes")
return
}
srv.server.UpdateConfig(opts...)
srv.setKey(cfg) srv.setKey(cfg)
} }
func (srv *dataBrokerServer) getOptions(cfg *config.Config) []databroker.ServerOption { func (srv *dataBrokerServer) getOptions(cfg *config.Config) ([]databroker.ServerOption, error) {
dataBrokerStorageConnectionString, err := cfg.Options.GetDataBrokerStorageConnectionString()
if err != nil {
return nil, fmt.Errorf("error loading databroker storage connection string: %w", err)
}
cert, _ := cfg.Options.GetDataBrokerCertificate() cert, _ := cfg.Options.GetDataBrokerCertificate()
return []databroker.ServerOption{ return []databroker.ServerOption{
databroker.WithGetSharedKey(cfg.Options.GetSharedKey), databroker.WithGetSharedKey(cfg.Options.GetSharedKey),
databroker.WithStorageType(cfg.Options.DataBrokerStorageType), databroker.WithStorageType(cfg.Options.DataBrokerStorageType),
databroker.WithStorageConnectionString(cfg.Options.DataBrokerStorageConnectionString), databroker.WithStorageConnectionString(dataBrokerStorageConnectionString),
databroker.WithStorageCAFile(cfg.Options.DataBrokerStorageCAFile), databroker.WithStorageCAFile(cfg.Options.DataBrokerStorageCAFile),
databroker.WithStorageCertificate(cert), databroker.WithStorageCertificate(cert),
databroker.WithStorageCertSkipVerify(cfg.Options.DataBrokerStorageCertSkipVerify), databroker.WithStorageCertSkipVerify(cfg.Options.DataBrokerStorageCertSkipVerify),
} }, nil
} }
func (srv *dataBrokerServer) setKey(cfg *config.Config) { func (srv *dataBrokerServer) setKey(cfg *config.Config) {