diff --git a/Makefile b/Makefile index bb2985fb..c7bb6b9e 100644 --- a/Makefile +++ b/Makefile @@ -211,8 +211,12 @@ deployment: dev-install: @echo "==> $@" @echo "deleting pods..." - @kubectl delete --force --selector app.kubernetes.io/name=pomerium pods || true + #@kubectl delete --force --selector app.kubernetes.io/name=pomerium pods || true + @kubectl delete deployment/pomerium --wait || true @$(KUSTOMIZE) build config/dev/local | kubectl apply --filename - + +.PHONY: dev-logs +dev-logs: @stern -n pomerium --selector app.kubernetes.io/name=pomerium .PHONY: dev-gen-secrets diff --git a/PROJECT b/PROJECT index d60c521e..a06694af 100644 --- a/PROJECT +++ b/PROJECT @@ -1,20 +1,21 @@ domain: pomerium.io layout: -- go.kubebuilder.io/v3 + - go.kubebuilder.io/v3 multigroup: true projectName: ingress-controller repo: github.com/pomerium/ingress-controller resources: -- controller: true - domain: networking.k8s.io - kind: Ingress - version: v1 -- api: - crdVersion: v1 - namespaced: true - domain: pomerium.io - group: ingress - kind: Settings - path: github.com/pomerium/ingress-controller/apis/ingress/v1 - version: v1 + - controller: true + domain: networking.k8s.io + kind: Ingress + version: v1 + - api: + crdVersion: v1 + namespaced: false + domain: pomerium.io + group: ingress + kind: Pomerium + plural: pomerium + path: github.com/pomerium/ingress-controller/apis/ingress/v1 + version: v1 version: "3" diff --git a/apis/ingress/v1/settings_types.go b/apis/ingress/v1/pomerium_types.go similarity index 93% rename from apis/ingress/v1/settings_types.go rename to apis/ingress/v1/pomerium_types.go index d0090c97..4163da12 100644 --- a/apis/ingress/v1/settings_types.go +++ b/apis/ingress/v1/pomerium_types.go @@ -137,7 +137,7 @@ type Storage struct { // Postgres specifies PostgreSQL database connection parameters // +kubebuilder:validation:Optional - Postgres *PostgresStorage `json:"postgresql"` + Postgres *PostgresStorage `json:"postgres"` } // Authenticate service configuration parameters @@ -155,8 +155,8 @@ type Authenticate struct { CallbackPath *string `json:"callbackPath,omitempty"` } -// SettingsSpec defines the desired state of Settings -type SettingsSpec struct { +// PomeriumSpec defines the desired state of Settings +type PomeriumSpec struct { // Authenticate sets authenticate service parameters // +kubebuilder:validation:Required Authenticate Authenticate `json:"authenticate"` @@ -202,33 +202,34 @@ type RouteStatus struct { Error string `json:"error,omitempty"` } -// SettingsStatus defines the observed state of Settings -type SettingsStatus struct { +// PomeriumStatus defines the observed state of Settings +type PomeriumStatus struct { Routes map[string]RouteStatus `json:"ingress"` } //+kubebuilder:object:root=true //+kubebuilder:subresource:status +//+kubebuilder:resource:path=pomerium -// Settings define runtime-configurable Pomerium settings +// Pomerium define runtime-configurable Pomerium settings // that do not fall into the category of deployment parameters -type Settings struct { +type Pomerium struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec SettingsSpec `json:"spec,omitempty"` - Status SettingsStatus `json:"status,omitempty"` + Spec PomeriumSpec `json:"spec,omitempty"` + Status PomeriumStatus `json:"status,omitempty"` } //+kubebuilder:object:root=true -// SettingsList contains a list of Settings -type SettingsList struct { +// PomeriumList contains a list of Settings +type PomeriumList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []Settings `json:"items"` + Items []Pomerium `json:"items"` } func init() { - SchemeBuilder.Register(&Settings{}, &SettingsList{}) + SchemeBuilder.Register(&Pomerium{}, &PomeriumList{}) } diff --git a/apis/ingress/v1/zz_generated.deepcopy.go b/apis/ingress/v1/zz_generated.deepcopy.go index 4909bd1b..607ce760 100644 --- a/apis/ingress/v1/zz_generated.deepcopy.go +++ b/apis/ingress/v1/zz_generated.deepcopy.go @@ -77,93 +77,7 @@ func (in *IdentityProvider) DeepCopy() *IdentityProvider { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PostgresStorage) DeepCopyInto(out *PostgresStorage) { - *out = *in - if in.TLSSecret != nil { - in, out := &in.TLSSecret, &out.TLSSecret - *out = new(string) - **out = **in - } - if in.CASecret != nil { - in, out := &in.CASecret, &out.CASecret - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgresStorage. -func (in *PostgresStorage) DeepCopy() *PostgresStorage { - if in == nil { - return nil - } - out := new(PostgresStorage) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RedisStorage) DeepCopyInto(out *RedisStorage) { - *out = *in - if in.TLSSecret != nil { - in, out := &in.TLSSecret, &out.TLSSecret - *out = new(string) - **out = **in - } - if in.CASecret != nil { - in, out := &in.CASecret, &out.CASecret - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisStorage. -func (in *RedisStorage) DeepCopy() *RedisStorage { - if in == nil { - return nil - } - out := new(RedisStorage) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RefreshDirectorySettings) DeepCopyInto(out *RefreshDirectorySettings) { - *out = *in - out.Interval = in.Interval - out.Timeout = in.Timeout -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RefreshDirectorySettings. -func (in *RefreshDirectorySettings) DeepCopy() *RefreshDirectorySettings { - if in == nil { - return nil - } - out := new(RefreshDirectorySettings) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteStatus) DeepCopyInto(out *RouteStatus) { - *out = *in - if in.LastReconciled != nil { - in, out := &in.LastReconciled, &out.LastReconciled - *out = (*in).DeepCopy() - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus. -func (in *RouteStatus) DeepCopy() *RouteStatus { - if in == nil { - return nil - } - out := new(RouteStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Settings) DeepCopyInto(out *Settings) { +func (in *Pomerium) DeepCopyInto(out *Pomerium) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -171,18 +85,18 @@ func (in *Settings) DeepCopyInto(out *Settings) { in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Settings. -func (in *Settings) DeepCopy() *Settings { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Pomerium. +func (in *Pomerium) DeepCopy() *Pomerium { if in == nil { return nil } - out := new(Settings) + out := new(Pomerium) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Settings) DeepCopyObject() runtime.Object { +func (in *Pomerium) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -190,31 +104,31 @@ func (in *Settings) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SettingsList) DeepCopyInto(out *SettingsList) { +func (in *PomeriumList) DeepCopyInto(out *PomeriumList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]Settings, len(*in)) + *out = make([]Pomerium, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SettingsList. -func (in *SettingsList) DeepCopy() *SettingsList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PomeriumList. +func (in *PomeriumList) DeepCopy() *PomeriumList { if in == nil { return nil } - out := new(SettingsList) + out := new(PomeriumList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SettingsList) DeepCopyObject() runtime.Object { +func (in *PomeriumList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -222,7 +136,7 @@ func (in *SettingsList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SettingsSpec) DeepCopyInto(out *SettingsSpec) { +func (in *PomeriumSpec) DeepCopyInto(out *PomeriumSpec) { *out = *in in.Authenticate.DeepCopyInto(&out.Authenticate) in.IdentityProvider.DeepCopyInto(&out.IdentityProvider) @@ -243,18 +157,18 @@ func (in *SettingsSpec) DeepCopyInto(out *SettingsSpec) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SettingsSpec. -func (in *SettingsSpec) DeepCopy() *SettingsSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PomeriumSpec. +func (in *PomeriumSpec) DeepCopy() *PomeriumSpec { if in == nil { return nil } - out := new(SettingsSpec) + out := new(PomeriumSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SettingsStatus) DeepCopyInto(out *SettingsStatus) { +func (in *PomeriumStatus) DeepCopyInto(out *PomeriumStatus) { *out = *in if in.Routes != nil { in, out := &in.Routes, &out.Routes @@ -265,12 +179,98 @@ func (in *SettingsStatus) DeepCopyInto(out *SettingsStatus) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SettingsStatus. -func (in *SettingsStatus) DeepCopy() *SettingsStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PomeriumStatus. +func (in *PomeriumStatus) DeepCopy() *PomeriumStatus { if in == nil { return nil } - out := new(SettingsStatus) + out := new(PomeriumStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PostgresStorage) DeepCopyInto(out *PostgresStorage) { + *out = *in + if in.TLSSecret != nil { + in, out := &in.TLSSecret, &out.TLSSecret + *out = new(string) + **out = **in + } + if in.CASecret != nil { + in, out := &in.CASecret, &out.CASecret + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgresStorage. +func (in *PostgresStorage) DeepCopy() *PostgresStorage { + if in == nil { + return nil + } + out := new(PostgresStorage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisStorage) DeepCopyInto(out *RedisStorage) { + *out = *in + if in.TLSSecret != nil { + in, out := &in.TLSSecret, &out.TLSSecret + *out = new(string) + **out = **in + } + if in.CASecret != nil { + in, out := &in.CASecret, &out.CASecret + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisStorage. +func (in *RedisStorage) DeepCopy() *RedisStorage { + if in == nil { + return nil + } + out := new(RedisStorage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RefreshDirectorySettings) DeepCopyInto(out *RefreshDirectorySettings) { + *out = *in + out.Interval = in.Interval + out.Timeout = in.Timeout +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RefreshDirectorySettings. +func (in *RefreshDirectorySettings) DeepCopy() *RefreshDirectorySettings { + if in == nil { + return nil + } + out := new(RefreshDirectorySettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteStatus) DeepCopyInto(out *RouteStatus) { + *out = *in + if in.LastReconciled != nil { + in, out := &in.LastReconciled, &out.LastReconciled + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus. +func (in *RouteStatus) DeepCopy() *RouteStatus { + if in == nil { + return nil + } + out := new(RouteStatus) in.DeepCopyInto(out) return out } diff --git a/cmd/all_in_one.go b/cmd/all_in_one.go index c57a24e6..c77ce13d 100644 --- a/cmd/all_in_one.go +++ b/cmd/all_in_one.go @@ -13,6 +13,7 @@ import ( "google.golang.org/grpc" "k8s.io/apimachinery/pkg/types" runtime_ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log" "github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/pkg/grpc/databroker" @@ -106,7 +107,7 @@ func (s *allCmd) exec(*cobra.Command, []string) error { func (s *allCmdOptions) getParam() (*allCmdParam, error) { settings, err := util.ParseNamespacedName(s.GlobalSettings) if err != nil { - return nil, fmt.Errorf("%s: %w", globalSettings, err) + return nil, fmt.Errorf("--%s: %w", globalSettings, err) } if err = s.Validate(); err != nil { @@ -198,6 +199,8 @@ func (s *allCmdParam) makeBootstrapConfig(opt allCmdOptions) error { // runConfigController runs an integrated Ingress + Settings CRD controller // TODO: it must be updated in case of configuration change to reconfigure shared_secret func (s *allCmdParam) runConfigControllers(ctx context.Context, runner *pomerium_ctrl.Runner) error { + logger := log.FromContext(ctx).WithName("config-controller") + logger.Info("waiting for config to be available") if err := runner.WaitForConfig(ctx); err != nil { return fmt.Errorf("waiting for boostrap config: %w", err) } @@ -205,6 +208,7 @@ func (s *allCmdParam) runConfigControllers(ctx context.Context, runner *pomerium if err != nil { return fmt.Errorf("build controller: %w", err) } + logger.Info("received config, starting up controllers") return c.Run(ctx) } diff --git a/cmd/ingress_opts.go b/cmd/ingress_opts.go index 8a2d40f1..a89439cf 100644 --- a/cmd/ingress_opts.go +++ b/cmd/ingress_opts.go @@ -18,7 +18,7 @@ type ingressControllerOpts struct { Namespaces []string DisableCertCheck bool UpdateStatusFromService string `validate:"required"` - GlobalSettings string + GlobalSettings string `validate:"required"` } const ( @@ -29,7 +29,7 @@ const ( debug = "debug" updateStatusFromService = "update-status-from-service" disableCertCheck = "disable-cert-check" - globalSettings = "global-settings" + globalSettings = "pomerium-config" ) func (s *ingressControllerOpts) setupFlags(flags *pflag.FlagSet) { diff --git a/config/crd/bases/ingress.pomerium.io_settings.yaml b/config/crd/bases/ingress.pomerium.io_pomerium.yaml similarity index 94% rename from config/crd/bases/ingress.pomerium.io_settings.yaml rename to config/crd/bases/ingress.pomerium.io_pomerium.yaml index e2c58079..e7470286 100644 --- a/config/crd/bases/ingress.pomerium.io_settings.yaml +++ b/config/crd/bases/ingress.pomerium.io_pomerium.yaml @@ -5,20 +5,20 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null - name: settings.ingress.pomerium.io + name: pomerium.ingress.pomerium.io spec: group: ingress.pomerium.io names: - kind: Settings - listKind: SettingsList - plural: settings - singular: settings + kind: Pomerium + listKind: PomeriumList + plural: pomerium + singular: pomerium scope: Namespaced versions: - name: v1 schema: openAPIV3Schema: - description: Settings define runtime-configurable Pomerium settings that do + description: Pomerium define runtime-configurable Pomerium settings that do not fall into the category of deployment parameters properties: apiVersion: @@ -34,7 +34,7 @@ spec: metadata: type: object spec: - description: SettingsSpec defines the desired state of Settings + description: PomeriumSpec defines the desired state of Settings properties: authenticate: description: Authenticate sets authenticate service parameters @@ -135,7 +135,7 @@ spec: description: Storage defines persistent storage for sessions and other data it will use in-memory if none specified see https://www.pomerium.com/docs/topics/data-storage properties: - postgresql: + postgres: description: Postgres specifies PostgreSQL database connection parameters properties: @@ -148,8 +148,8 @@ spec: type: string secret: description: Secret specifies a name of a Secret that must - contain `postgresql_connection_string` for the connection - DSN format and parameters, see https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING + contain `connection` key for the connection DSN format and + parameters, see https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING the following keywords are not allowed to be part of the parameters, as they must be populated via `tlsCecret` and `caSecret` fields @@ -200,7 +200,7 @@ spec: - secrets type: object status: - description: SettingsStatus defines the observed state of Settings + description: PomeriumStatus defines the observed state of Settings properties: ingress: additionalProperties: diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index cea163cf..98257bbd 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -2,20 +2,9 @@ # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: -- bases/ingress.pomerium.io_settings.yaml + - bases/ingress.pomerium.io_pomerium.yaml #+kubebuilder:scaffold:crdkustomizeresource -patchesStrategicMerge: -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. -# patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_settings.yaml -#+kubebuilder:scaffold:crdkustomizewebhookpatch - -# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. -# patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_settings.yaml -#+kubebuilder:scaffold:crdkustomizecainjectionpatch - # the following config is for teaching kustomize how to do kustomization for CRDs. configurations: -- kustomizeconfig.yaml + - kustomizeconfig.yaml diff --git a/config/crd/patches/cainjection_in_ingress_settings.yaml b/config/crd/patches/cainjection_in_ingress_settings.yaml deleted file mode 100644 index f4f60b60..00000000 --- a/config/crd/patches/cainjection_in_ingress_settings.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: settings.ingress.pomerium.io diff --git a/config/crd/patches/webhook_in_ingress_settings.yaml b/config/crd/patches/webhook_in_ingress_settings.yaml deleted file mode 100644 index b165d429..00000000 --- a/config/crd/patches/webhook_in_ingress_settings.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: settings.ingress.pomerium.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/pomerium/deployment/args.yaml b/config/pomerium/deployment/args.yaml index 96ef688a..677a2dd9 100644 --- a/config/pomerium/deployment/args.yaml +++ b/config/pomerium/deployment/args.yaml @@ -9,7 +9,7 @@ spec: - name: pomerium args: - all-in-one - - --global-settings=$(POMERIUM_NAMESPACE)/settings + - --pomerium-config=$(POMERIUM_NAMESPACE)/global - --update-status-from-service=$(POMERIUM_NAMESPACE)/pomerium-proxy - --metrics-bind-address=$(POD_IP):9090 env: diff --git a/config/pomerium/kustomization.yaml b/config/pomerium/kustomization.yaml index 5bb1e171..f4bdcad7 100644 --- a/config/pomerium/kustomization.yaml +++ b/config/pomerium/kustomization.yaml @@ -6,3 +6,4 @@ resources: - ./ingressclass.yaml - ./deployment - ./service + - ./rbac diff --git a/config/pomerium/rbac/role.yaml b/config/pomerium/rbac/role.yaml index 3d8b9644..bde45348 100644 --- a/config/pomerium/rbac/role.yaml +++ b/config/pomerium/rbac/role.yaml @@ -42,7 +42,7 @@ rules: - apiGroups: - ingress.pomerium.io resources: - - settings + - pomerium verbs: - get - list @@ -50,7 +50,7 @@ rules: - apiGroups: - ingress.pomerium.io resources: - - settings/status + - pomerium/status verbs: - get - update diff --git a/controllers/ingress/controller.go b/controllers/ingress/controller.go index 4016619d..3b99803b 100644 --- a/controllers/ingress/controller.go +++ b/controllers/ingress/controller.go @@ -152,7 +152,7 @@ func (r *ingressController) SetupWithManager(mgr ctrl.Manager) error { {&corev1.Secret{}, &r.secretKind, r.getDependantIngressFn}, {&corev1.Service{}, &r.serviceKind, r.getDependantIngressFn}, {&corev1.Endpoints{}, &r.endpointsKind, r.getDependantIngressFn}, - {&icsv1.Settings{}, &r.settingsKind, nil}, + {&icsv1.Pomerium{}, &r.settingsKind, nil}, } { gvk, err := apiutil.GVKForObject(o.Object, r.Scheme) if err != nil { diff --git a/controllers/ingress/controller_integration_test.go b/controllers/ingress/controller_integration_test.go index c8fb4313..0533b9de 100644 --- a/controllers/ingress/controller_integration_test.go +++ b/controllers/ingress/controller_integration_test.go @@ -204,7 +204,7 @@ func (s *ControllerTestSuite) deleteAll() { s.NoError(s.Client.Delete(ctx, &secrets.Items[i])) } - settings := new(icsv1.SettingsList) + settings := new(icsv1.PomeriumList) s.NoError(s.Client.List(ctx, settings)) for i := range settings.Items { s.NoError(s.Client.Delete(ctx, &settings.Items[i])) @@ -739,7 +739,7 @@ func (s *ControllerTestSuite) TestCustomSecrets() { func (s *ControllerTestSuite) TestSettingsStatusUpdate() { ctx := context.Background() - name := types.NamespacedName{Namespace: "default", Name: "global-settings"} + name := types.NamespacedName{Namespace: "default", Name: "config"} reporter := reporter.IngressSettingsReporter{ SettingsReporter: reporter.SettingsReporter{ NamespacedName: name, @@ -751,9 +751,9 @@ func (s *ControllerTestSuite) TestSettingsStatusUpdate() { s.NoError(s.Client.Create(ctx, to.Ingress)) ingressName := types.NamespacedName{Namespace: to.Ingress.Namespace, Name: to.Ingress.Name} - gs := icsv1.Settings{ + gs := icsv1.Pomerium{ ObjectMeta: metav1.ObjectMeta{Name: name.Name, Namespace: name.Namespace}, - Spec: icsv1.SettingsSpec{ + Spec: icsv1.PomeriumSpec{ IdentityProvider: icsv1.IdentityProvider{ Provider: "oidc", Secret: "secret", diff --git a/controllers/reporter/pomerium.go b/controllers/reporter/pomerium.go index d705a237..db6c7b75 100644 --- a/controllers/reporter/pomerium.go +++ b/controllers/reporter/pomerium.go @@ -25,8 +25,8 @@ type SettingsReporter struct { client.Client } -func (s *SettingsReporter) getSettings(ctx context.Context) (*icsv1.Settings, error) { - var obj icsv1.Settings +func (s *SettingsReporter) getSettings(ctx context.Context) (*icsv1.Pomerium, error) { + var obj icsv1.Pomerium if err := s.Get(ctx, s.NamespacedName, &obj); err != nil { return nil, fmt.Errorf("get %s: %w", s.NamespacedName, err) } diff --git a/controllers/settings/controller.go b/controllers/settings/controller.go index 31fb557b..7fbbd71e 100644 --- a/controllers/settings/controller.go +++ b/controllers/settings/controller.go @@ -11,6 +11,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/source" icsv1 "github.com/pomerium/ingress-controller/apis/ingress/v1" @@ -67,7 +68,7 @@ func NewSettingsController( } c, err := ctrl.NewControllerManagedBy(mgr). - For(new(icsv1.Settings)).Build(stc) + For(new(icsv1.Pomerium)).Build(stc) if err != nil { return fmt.Errorf("build controller: %w", err) } @@ -95,6 +96,7 @@ func NewSettingsController( // Reconcile syncs Settings CRD with pomerium databroker func (c *settingsController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { if req.NamespacedName != c.name { + log.FromContext(ctx).Info("reconcile", "got", req.NamespacedName, "want", c.name) return ctrl.Result{}, nil } diff --git a/controllers/settings/deps.go b/controllers/settings/deps.go index d7283176..ae2686bd 100644 --- a/controllers/settings/deps.go +++ b/controllers/settings/deps.go @@ -12,7 +12,7 @@ func (c *settingsController) updateDependencies(cfg *model.Config) { } func updateDependencies(cfg *model.Config, r model.Registry, scheme *runtime.Scheme) { - key := model.ObjectKey(&cfg.Settings, scheme) + key := model.ObjectKey(&cfg.Pomerium, scheme) r.DeleteCascade(key) for _, s := range cfg.Certs { diff --git a/controllers/settings/fetch.go b/controllers/settings/fetch.go index 2c20dd4e..cc8dbdbc 100644 --- a/controllers/settings/fetch.go +++ b/controllers/settings/fetch.go @@ -16,7 +16,7 @@ import ( // FetchConfig returns func FetchConfig(ctx context.Context, client client.Client, name types.NamespacedName) (*model.Config, error) { var cfg model.Config - if err := client.Get(ctx, name, &cfg.Settings); err != nil { + if err := client.Get(ctx, name, &cfg.Pomerium); err != nil { return nil, fmt.Errorf("get %s: %w", name, err) } diff --git a/controllers/settings/fetch_test.go b/controllers/settings/fetch_test.go index 75a3d483..12285819 100644 --- a/controllers/settings/fetch_test.go +++ b/controllers/settings/fetch_test.go @@ -90,48 +90,48 @@ func TestFetchConstraints(t *testing.T) { for _, tc := range []struct { name string - spec icsv1.SettingsSpec + spec icsv1.PomeriumSpec check func(assert.TestingT, error, ...any) bool }{ - {"ok", icsv1.SettingsSpec{ + {"ok", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, Secrets: "pomerium/bootstrap-secrets", }, assert.NoError}, - {"bootstrap secret is mandatory", icsv1.SettingsSpec{ + {"bootstrap secret is mandatory", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, }, assert.Error}, - {"idp secret is mandatory", icsv1.SettingsSpec{ + {"idp secret is mandatory", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{}, Certificates: []string{}, Secrets: "pomerium/bootstrap-secrets", }, assert.Error}, - {"no empty storage", icsv1.SettingsSpec{ + {"no empty storage", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, Secrets: "pomerium/bootstrap-secrets", Storage: &icsv1.Storage{}, }, assert.Error}, - {"redis: secret missing", icsv1.SettingsSpec{ + {"redis: secret missing", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, Secrets: "pomerium/bootstrap-secrets", Storage: &icsv1.Storage{Redis: &icsv1.RedisStorage{}}, }, assert.Error}, - {"redis: secret present", icsv1.SettingsSpec{ + {"redis: secret present", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, Secrets: "pomerium/bootstrap-secrets", Storage: &icsv1.Storage{Redis: &icsv1.RedisStorage{Secret: "pomerium/redis"}}, }, assert.NoError}, - {"redis: ca + tls", icsv1.SettingsSpec{ + {"redis: ca + tls", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, @@ -142,21 +142,21 @@ func TestFetchConstraints(t *testing.T) { TLSSecret: proto.String("pomerium/redis-tls"), }}, }, assert.NoError}, - {"postgres: secret missing", icsv1.SettingsSpec{ + {"postgres: secret missing", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, Secrets: "pomerium/bootstrap-secrets", Storage: &icsv1.Storage{Postgres: &icsv1.PostgresStorage{}}, }, assert.Error}, - {"postgres: secret present", icsv1.SettingsSpec{ + {"postgres: secret present", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, Secrets: "pomerium/bootstrap-secrets", Storage: &icsv1.Storage{Postgres: &icsv1.PostgresStorage{Secret: "pomerium/postgres"}}, }, assert.NoError}, - {"postgres: ca + tls", icsv1.SettingsSpec{ + {"postgres: ca + tls", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{}, IdentityProvider: icsv1.IdentityProvider{Secret: "pomerium/idp-secrets"}, Certificates: []string{}, @@ -169,9 +169,9 @@ func TestFetchConstraints(t *testing.T) { }, assert.NoError}, } { t.Run(tc.name, func(t *testing.T) { - mc.EXPECT().Get(ctx, settingsName, gomock.AssignableToTypeOf(new(icsv1.Settings))). - Do(func(_ context.Context, _ types.NamespacedName, dst *icsv1.Settings) { - *dst = icsv1.Settings{ + mc.EXPECT().Get(ctx, settingsName, gomock.AssignableToTypeOf(new(icsv1.Pomerium))). + Do(func(_ context.Context, _ types.NamespacedName, dst *icsv1.Pomerium) { + *dst = icsv1.Pomerium{ ObjectMeta: metav1.ObjectMeta{ Name: settingsName.Name, Namespace: settingsName.Namespace, diff --git a/controllers/settings/integration_test.go b/controllers/settings/integration_test.go index 6b22e9f8..baf21163 100644 --- a/controllers/settings/integration_test.go +++ b/controllers/settings/integration_test.go @@ -77,7 +77,7 @@ func (s *ControllerTestSuite) deleteAll() { s.NoError(s.Client.Delete(ctx, &secrets.Items[i])) } - settings := new(icsv1.SettingsList) + settings := new(icsv1.PomeriumList) s.NoError(s.Client.List(ctx, settings)) for i := range settings.Items { s.NoError(s.Client.Delete(ctx, &settings.Items[i])) @@ -119,33 +119,33 @@ func (s *ControllerTestSuite) TestValidation() { ctx := context.Background() for i, tc := range []struct { name string - spec icsv1.SettingsSpec + spec icsv1.PomeriumSpec expectError bool }{ - {"empty spec", icsv1.SettingsSpec{}, true}, - {"ok spec", icsv1.SettingsSpec{ + {"empty spec", icsv1.PomeriumSpec{}, true}, + {"ok spec", icsv1.PomeriumSpec{ Authenticate: auth, IdentityProvider: idp, Secrets: "pomerium/default-secrets", }, false}, - {"secrets required", icsv1.SettingsSpec{ + {"secrets required", icsv1.PomeriumSpec{ Authenticate: auth, IdentityProvider: idp, }, true}, - {"invalid auth url", icsv1.SettingsSpec{ + {"invalid auth url", icsv1.PomeriumSpec{ Authenticate: icsv1.Authenticate{URL: "hostname"}, IdentityProvider: idp, Secrets: "pomerium/default-secrets", }, true}, - {"auth required", icsv1.SettingsSpec{ + {"auth required", icsv1.PomeriumSpec{ IdentityProvider: idp, Secrets: "pomerium/default-secrets", }, true}, - {"idp required", icsv1.SettingsSpec{ + {"idp required", icsv1.PomeriumSpec{ Authenticate: auth, Secrets: "pomerium/default-secrets", }, true}, - {"idp secret required", icsv1.SettingsSpec{ + {"idp secret required", icsv1.PomeriumSpec{ Authenticate: auth, Secrets: "pomerium/default-secrets", IdentityProvider: icsv1.IdentityProvider{ @@ -153,7 +153,7 @@ func (s *ControllerTestSuite) TestValidation() { Provider: "oidc", }, }, true}, - {"idp provider required", icsv1.SettingsSpec{ + {"idp provider required", icsv1.PomeriumSpec{ Authenticate: auth, IdentityProvider: icsv1.IdentityProvider{ Secret: "secret", @@ -161,7 +161,7 @@ func (s *ControllerTestSuite) TestValidation() { }, Secrets: "pomerium/default-secrets", }, true}, - {"idp provider enum", icsv1.SettingsSpec{ + {"idp provider enum", icsv1.PomeriumSpec{ Authenticate: auth, IdentityProvider: icsv1.IdentityProvider{ Secret: "secret", @@ -171,7 +171,7 @@ func (s *ControllerTestSuite) TestValidation() { }, true}, } { s.T().Run(tc.name, func(t *testing.T) { - err := s.Client.Create(ctx, &icsv1.Settings{ + err := s.Client.Create(ctx, &icsv1.Pomerium{ ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("settings-%d", i), Namespace: "default"}, Spec: tc.spec, }) diff --git a/deployment.yaml b/deployment.yaml index 01c460c8..85218ac7 100644 --- a/deployment.yaml +++ b/deployment.yaml @@ -13,20 +13,20 @@ metadata: creationTimestamp: null labels: app.kubernetes.io/name: pomerium - name: settings.ingress.pomerium.io + name: pomerium.ingress.pomerium.io spec: group: ingress.pomerium.io names: - kind: Settings - listKind: SettingsList - plural: settings - singular: settings + kind: Pomerium + listKind: PomeriumList + plural: pomerium + singular: pomerium scope: Namespaced versions: - name: v1 schema: openAPIV3Schema: - description: Settings define runtime-configurable Pomerium settings that do + description: Pomerium define runtime-configurable Pomerium settings that do not fall into the category of deployment parameters properties: apiVersion: @@ -42,7 +42,7 @@ spec: metadata: type: object spec: - description: SettingsSpec defines the desired state of Settings + description: PomeriumSpec defines the desired state of Settings properties: authenticate: description: Authenticate sets authenticate service parameters @@ -143,7 +143,7 @@ spec: description: Storage defines persistent storage for sessions and other data it will use in-memory if none specified see https://www.pomerium.com/docs/topics/data-storage properties: - postgresql: + postgres: description: Postgres specifies PostgreSQL database connection parameters properties: @@ -156,8 +156,8 @@ spec: type: string secret: description: Secret specifies a name of a Secret that must - contain `postgresql_connection_string` for the connection - DSN format and parameters, see https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING + contain `connection` key for the connection DSN format and + parameters, see https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING the following keywords are not allowed to be part of the parameters, as they must be populated via `tlsCecret` and `caSecret` fields @@ -208,7 +208,7 @@ spec: - secrets type: object status: - description: SettingsStatus defines the observed state of Settings + description: PomeriumStatus defines the observed state of Settings properties: ingress: additionalProperties: @@ -243,6 +243,14 @@ spec: --- apiVersion: v1 kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: pomerium + name: pomerium-controller + namespace: pomerium +--- +apiVersion: v1 +kind: ServiceAccount metadata: labels: app.kubernetes.io/name: pomerium @@ -251,6 +259,72 @@ metadata: --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: pomerium + name: pomerium-controller +rules: +- apiGroups: + - "" + resources: + - services + - endpoints + - secrets + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - services/status + - secrets/status + - endpoints/status + verbs: + - get +- apiGroups: + - networking.k8s.io + resources: + - ingresses + - ingressclasses + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - get + - patch + - update +- apiGroups: + - ingress.pomerium.io + resources: + - pomerium + verbs: + - get + - list + - watch +- apiGroups: + - ingress.pomerium.io + resources: + - pomerium/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole metadata: labels: app.kubernetes.io/name: pomerium @@ -265,6 +339,21 @@ rules: --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: pomerium + name: pomerium-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: pomerium-controller +subjects: +- kind: ServiceAccount + name: pomerium-controller + namespace: pomerium +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/name: pomerium @@ -336,7 +425,7 @@ spec: containers: - args: - all-in-one - - --global-settings=$(POMERIUM_NAMESPACE)/settings + - --pomerium-config=$(POMERIUM_NAMESPACE)/global - --update-status-from-service=$(POMERIUM_NAMESPACE)/pomerium-proxy - --metrics-bind-address=$(POD_IP):9090 env: diff --git a/go.sum b/go.sum index 20899bdb..8c75c0b2 100644 --- a/go.sum +++ b/go.sum @@ -2636,8 +2636,6 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyz sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= sigs.k8s.io/controller-runtime v0.12.2 h1:nqV02cvhbAj7tbt21bpPpTByrXGn2INHRsi39lXy9sE= sigs.k8s.io/controller-runtime v0.12.2/go.mod h1:qKsk4WE6zW2Hfj0G4v10EnNB2jMG1C+NTb8h+DwCoU0= -sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20220629132207-365ae09c4c6c h1:DDeXe8254mA+hjwgBZD5tvUdB/iRun+Gu1wSqM8XS4c= -sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20220629132207-365ae09c4c6c/go.mod h1:nLkMD2WB4Jcix1qfVuJeOF4j5y/VfyeOIlTxG5Wj9co= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20220706151251-15154aaa6767 h1:vtJnIIQUlw5vjbCFB1wLLkHKTb07+aswYve6bmQzBdg= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20220706151251-15154aaa6767/go.mod h1:nLkMD2WB4Jcix1qfVuJeOF4j5y/VfyeOIlTxG5Wj9co= sigs.k8s.io/controller-tools v0.9.2 h1:AkTE3QAdz9LS4iD3EJvHyYxBkg/g9fTbgiYsrcsFCcM= diff --git a/model/ingress_config.go b/model/ingress_config.go index 87b9986a..5d68031c 100644 --- a/model/ingress_config.go +++ b/model/ingress_config.go @@ -77,7 +77,7 @@ func (s StorageSecrets) Validate() error { // Config represents global configuration type Config struct { // Settings define global settings parameters - icsv1.Settings + icsv1.Pomerium // Secrets are key secrets Secrets *corev1.Secret // Certs are fetched certs from settings.Certificates diff --git a/pomerium/config.go b/pomerium/config.go index 351d1d73..ecdecdd0 100644 --- a/pomerium/config.go +++ b/pomerium/config.go @@ -79,7 +79,7 @@ func applyIDP(p *pb.Config, c *model.Config) error { } func applyIDPProviderRefreshTimeouts(p *pb.Config, c *model.Config) error { - rd := c.Settings.Spec.IdentityProvider.RefreshDirectory + rd := c.Pomerium.Spec.IdentityProvider.RefreshDirectory if rd == nil { return nil }