diff --git a/cmd/all_in_one.go b/cmd/all_in_one.go index 547e88fb..2dfc873d 100644 --- a/cmd/all_in_one.go +++ b/cmd/all_in_one.go @@ -339,7 +339,7 @@ func (s *allCmdParam) buildController(ctx context.Context, cfg *config.Config) ( client := databroker.NewDataBrokerServiceClient(conn) var reconciler pomerium.Reconciler if s.syncAPIURL != "" { - reconciler = pomerium.NewAPIReconciler(s.syncAPIURL, s.syncAPIToken) + reconciler = pomerium.NewAPIReconciler(s.syncAPIURL, s.syncAPIToken, s.cfg.Options) } else { reconciler = pomerium.NewDataBrokerReconciler(client, s.dumpConfigDiff) } diff --git a/cmd/controller.go b/cmd/controller.go index 041ff352..892e5508 100644 --- a/cmd/controller.go +++ b/cmd/controller.go @@ -14,6 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/config" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + pomerium_config "github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/pkg/grpc/databroker" "github.com/pomerium/pomerium/pkg/grpcutil" @@ -167,7 +168,8 @@ func (s *controllerCmd) buildController(ctx context.Context) (*controllers.Contr } if s.SyncAPIURL != "" { - c.Reconciler = pomerium.NewAPIReconciler(s.SyncAPIURL, s.SyncAPIToken) + c.Reconciler = pomerium.NewAPIReconciler( + s.SyncAPIURL, s.SyncAPIToken, pomerium_config.NewDefaultOptions()) c.MgrOpts.LeaderElection = true c.MgrOpts.LeaderElectionID = s.leaderElectionID c.MgrOpts.LeaderElectionNamespace = s.leaderElectionNamespace diff --git a/pomerium/sync_api.go b/pomerium/sync_api.go index 2e567729..8a7c9982 100644 --- a/pomerium/sync_api.go +++ b/pomerium/sync_api.go @@ -35,14 +35,15 @@ import ( // NewAPIReconciler initializes a reconciler that syncs using the unified API, // for the given API url and API token. func NewAPIReconciler( - url, token string, + url, token string, baseOptions *config.Options, ) Reconciler { client := sdk.NewClient( sdk.WithURL(url), sdk.WithAPIToken(token)) return &APIReconciler{ - apiClient: client, - secretsMap: model.NewTLSSecretsMap(), + apiClient: client, + baseOptions: baseOptions, + secretsMap: model.NewTLSSecretsMap(), } } @@ -57,7 +58,8 @@ type APIReconciler struct { apiClient sdk.Client k8sClient client.Client - secretsMap *model.TLSSecretsMap + baseOptions *config.Options + secretsMap *model.TLSSecretsMap } const ( @@ -341,8 +343,8 @@ func (r *APIReconciler) SetConfig(ctx context.Context, cfg *model.Config) (chang pbConfig.Settings.Certificates = nil pbConfig.Settings.CertificateAuthority = nil - // Apply all Core defaults. - mergedSettings := config.NewDefaultOptions() + // Layer settings on top of the baseOptions. + mergedSettings := *r.baseOptions mergedSettings.ApplySettings(ctx, nil, pbConfig.Settings) settings, err := convertProto[*configpb.Settings](mergedSettings.ToProto().GetSettings()) diff --git a/pomerium/sync_api_test.go b/pomerium/sync_api_test.go index 2389d3ab..65c55878 100644 --- a/pomerium/sync_api_test.go +++ b/pomerium/sync_api_test.go @@ -58,8 +58,9 @@ func setupReconciler(t *testing.T) ( k8sClient := controllers_mock.NewMockClient(ctrl) r := &APIReconciler{ - apiClient: apiClient, - secretsMap: model.NewTLSSecretsMap(), + apiClient: apiClient, + baseOptions: config.NewDefaultOptions(), + secretsMap: model.NewTLSSecretsMap(), } r.SetK8sClient(k8sClient) return apiClient, k8sClient, r @@ -1099,6 +1100,45 @@ func TestAPIReconciler_SetConfig(t *testing.T) { assert.False(t, changes) assert.NoError(t, err) }) + + t.Run("base options", func(t *testing.T) { + apiClient, _, r := setupReconciler(t) + r.baseOptions = &config.Options{ + Addr: ":8443", + } + ctx := t.Context() + + apiClient.EXPECT().GetSettings(ctx, RequestEq(&configpb.GetSettingsRequest{})). + Return(&connect.Response[configpb.GetSettingsResponse]{ + Msg: &configpb.GetSettingsResponse{ + Settings: &configpb.Settings{ + Id: new("settings-id-123"), + }, + }, + }, nil) + + // The address from the base options should be preserved. + expectedSettings := &configpb.Settings{ + Id: new("settings-id-123"), + Address: new(":8443"), + AuthenticateServiceUrl: new("https://authenticate.localhost.pomerium.io"), + IdpClientId: new("CLIENT_ID"), + IdpClientSecret: new("CLIENT_SECRET"), + IdpProvider: new("oidc"), + IdpProviderUrl: new("https://idp.example.com"), + PassIdentityHeaders: new(true), + } + + apiClient.EXPECT().UpdateSettings(ctx, RequestEq(&configpb.UpdateSettingsRequest{ + Settings: expectedSettings, + })).Return(&connect.Response[configpb.UpdateSettingsResponse]{ + Msg: &configpb.UpdateSettingsResponse{}, + }, nil) + + changes, err := r.SetConfig(ctx, cfg) + assert.True(t, changes) + assert.NoError(t, err) + }) } func TestAPIReconciler_syncOneSecret(t *testing.T) {