From 31c7066fadd9e4c859370b0777dbd4db5657c634 Mon Sep 17 00:00:00 2001 From: wasaga <> Date: Thu, 19 Aug 2021 11:17:56 -0400 Subject: [PATCH] ingress not found; config identity check --- TODO.md | 18 +++++++++++++----- controllers/controller.go | 5 ++++- controllers/suite_test.go | 16 ---------------- pomerium/sync.go | 38 ++++++++++++++++++++++++++------------ 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/TODO.md b/TODO.md index 4b095cf7..725e860c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,10 +1,18 @@ -- support TLS certs - -* monitor referenced secret & service for changes +# TODO -- config transformation tests - record ingress state change events +- config transformation tests - envoy config validation - watch only specific namespace(s) - run against k8s ingress conformance tests -- test with cert-manager +- support http01 challenge +- recover after redis wipe: currently not detecting that +- potential leak of ingresses if removed while controller is unavailable +- certificate matching: if a matching cert already exists in the databroker config, then it might be chosen + even if tls spec says otherwise + +# Done + +- monitor referenced secret & service for changes +- map annotations to route props +- support TLS certs diff --git a/controllers/controller.go b/controllers/controller.go index 6d454f57..aef6f1e0 100644 --- a/controllers/controller.go +++ b/controllers/controller.go @@ -137,7 +137,10 @@ func (r Controller) getDependantIngressFn(kind string) func(a client.Object) []r func (r Controller) isIngressNotFound(err error) bool { if status := apierrors.APIStatus(nil); errors.As(err, &status) { - return status.Status().Reason == metav1.StatusReasonNotFound && status.Status().Kind == r.ingressKind + s := status.Status() + return s.Reason == metav1.StatusReasonNotFound && + s.Details != nil && + s.Details.Kind == r.ingressKind } return false } diff --git a/controllers/suite_test.go b/controllers/suite_test.go index a6037b0a..24d97059 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -1,19 +1,3 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - package controllers import ( diff --git a/pomerium/sync.go b/pomerium/sync.go index 1b8de9d6..b4836100 100644 --- a/pomerium/sync.go +++ b/pomerium/sync.go @@ -1,6 +1,7 @@ package pomerium import ( + "bytes" "context" "fmt" @@ -10,6 +11,7 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/log" "github.com/pomerium/ingress-controller/model" pomerium "github.com/pomerium/pomerium/pkg/grpc/config" @@ -30,7 +32,7 @@ type ConfigReconciler struct { // Upsert should update or create the pomerium routes corresponding to this ingress func (r *ConfigReconciler) Upsert(ctx context.Context, ic *model.IngressConfig) error { - cfg, err := r.getConfig(ctx) + cfg, prevBytes, err := r.getConfig(ctx) if err != nil { return fmt.Errorf("get config: %w", err) } @@ -40,7 +42,7 @@ func (r *ConfigReconciler) Upsert(ctx context.Context, ic *model.IngressConfig) if err := upsertCerts(cfg, ic); err != nil { return fmt.Errorf("updating certs: %w", err) } - if err := r.saveConfig(ctx, cfg); err != nil { + if err := r.saveConfig(ctx, cfg, prevBytes); err != nil { return fmt.Errorf("updating pomerium config: %w", err) } return nil @@ -48,20 +50,23 @@ func (r *ConfigReconciler) Upsert(ctx context.Context, ic *model.IngressConfig) // Delete should delete pomerium routes corresponding to this ingress name func (r *ConfigReconciler) Delete(ctx context.Context, namespacedName types.NamespacedName) error { - cfg, err := r.getConfig(ctx) + cfg, prevBytes, err := r.getConfig(ctx) if err != nil { return fmt.Errorf("get pomerium config: %w", err) } if err := deleteRoutes(cfg, namespacedName); err != nil { return fmt.Errorf("deleting pomerium config records %s: %w", namespacedName.String(), err) } - if err := r.saveConfig(ctx, cfg); err != nil { + if err := removeUnusedCerts(cfg); err != nil { + return fmt.Errorf("removing unused certs: %w", err) + } + if err := r.saveConfig(ctx, cfg, prevBytes); err != nil { return fmt.Errorf("updating pomerium config: %w", err) } return nil } -func (r *ConfigReconciler) getConfig(ctx context.Context) (*pomerium.Config, error) { +func (r *ConfigReconciler) getConfig(ctx context.Context) (*pomerium.Config, []byte, error) { cfg := new(pomerium.Config) any := protoutil.NewAny(cfg) var hdr metadata.MD @@ -70,22 +75,27 @@ func (r *ConfigReconciler) getConfig(ctx context.Context) (*pomerium.Config, err Id: configID, }, grpc.Header(&hdr)) if status.Code(err) == codes.NotFound { - return &pomerium.Config{}, nil + return &pomerium.Config{}, nil, nil } else if err != nil { - return nil, fmt.Errorf("get pomerium config: %w", err) + return nil, nil, fmt.Errorf("get pomerium config: %w", err) } if err := resp.GetRecord().GetData().UnmarshalTo(cfg); err != nil { - return nil, fmt.Errorf("unmarshal current config: %w", err) + return nil, nil, fmt.Errorf("unmarshal current config: %w", err) } - return cfg, nil + return cfg, resp.GetRecord().GetData().GetValue(), nil } -func (r *ConfigReconciler) saveConfig(ctx context.Context, cfg *pomerium.Config) error { - fmt.Println(protojson.Format(cfg)) - +func (r *ConfigReconciler) saveConfig(ctx context.Context, cfg *pomerium.Config, prevBytes []byte) error { + logger := log.FromContext(ctx) any := protoutil.NewAny(cfg) + + if bytes.Equal(prevBytes, any.GetValue()) { + logger.Info("no changes in pomerium config") + return nil + } + if _, err := r.Put(ctx, &databroker.PutRequest{ Record: &databroker.Record{ Type: any.GetTypeUrl(), @@ -95,5 +105,9 @@ func (r *ConfigReconciler) saveConfig(ctx context.Context, cfg *pomerium.Config) }); err != nil { return err } + + logger.Info("new pomerium config applied") + fmt.Println(protojson.Format(cfg)) + return nil }