diff --git a/apis/ingress/v1/pomerium_types.go b/apis/ingress/v1/pomerium_types.go index 9e8cc160..31e4d560 100644 --- a/apis/ingress/v1/pomerium_types.go +++ b/apis/ingress/v1/pomerium_types.go @@ -232,6 +232,10 @@ type PomeriumSpec struct { // +optional Certificates []string `json:"certificates"` + // CASecret should refer to k8s secrets with key ca.crt containing a CA certificate. + // +optional + CASecrets []string `json:"caSecrets"` + // Secrets references a Secret with Pomerium bootstrap parameters. // //

diff --git a/apis/ingress/v1/zz_generated.deepcopy.go b/apis/ingress/v1/zz_generated.deepcopy.go index bf346a66..a3f698e0 100644 --- a/apis/ingress/v1/zz_generated.deepcopy.go +++ b/apis/ingress/v1/zz_generated.deepcopy.go @@ -186,6 +186,11 @@ func (in *PomeriumSpec) DeepCopyInto(out *PomeriumSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.CASecrets != nil { + in, out := &in.CASecrets, &out.CASecrets + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.Storage != nil { in, out := &in.Storage, &out.Storage *out = new(Storage) diff --git a/config/crd/bases/ingress.pomerium.io_pomerium.yaml b/config/crd/bases/ingress.pomerium.io_pomerium.yaml index 8ab6e121..08004c0b 100644 --- a/config/crd/bases/ingress.pomerium.io_pomerium.yaml +++ b/config/crd/bases/ingress.pomerium.io_pomerium.yaml @@ -63,6 +63,12 @@ spec: required: - url type: object + caSecrets: + description: CASecret should refer to k8s secrets with key ca.crt + containing a CA certificate. + items: + type: string + type: array certificates: description: Certificates is a list of secrets of type TLS to use format: namespace/name diff --git a/controllers/settings/fetch.go b/controllers/settings/fetch.go index b356c407..9a411112 100644 --- a/controllers/settings/fetch.go +++ b/controllers/settings/fetch.go @@ -101,6 +101,16 @@ func fetchConfigSecrets(ctx context.Context, client client.Client, cfg *model.Co s := cfg.Spec return applyAll( apply("bootstrap secret", required(&s.Secrets), &cfg.Secrets), + func() error { + for _, caSecret := range s.CASecrets { + secret, err := get(caSecret)() + if err != nil { + return fmt.Errorf("ca: %w", err) + } + cfg.CASecrets = append(cfg.CASecrets, secret) + } + return nil + }, apply("secret", required(&s.IdentityProvider.Secret), &cfg.IdpSecret), apply("request params", optional(s.IdentityProvider.RequestParamsSecret), &cfg.RequestParams), apply("service account", optional(s.IdentityProvider.ServiceAccountFromSecret), &cfg.IdpServiceAccount), diff --git a/deployment.yaml b/deployment.yaml index f81f036e..c4d91f05 100644 --- a/deployment.yaml +++ b/deployment.yaml @@ -71,6 +71,12 @@ spec: required: - url type: object + caSecrets: + description: CASecret should refer to k8s secrets with key ca.crt + containing a CA certificate. + items: + type: string + type: array certificates: description: Certificates is a list of secrets of type TLS to use format: namespace/name diff --git a/model/ingress_config.go b/model/ingress_config.go index b33bb91a..dbacfe4a 100644 --- a/model/ingress_config.go +++ b/model/ingress_config.go @@ -80,6 +80,8 @@ type Config struct { icsv1.Pomerium // Secrets are key secrets Secrets *corev1.Secret + // CASecrets are ca secrets + CASecrets []*corev1.Secret // Certs are fetched certs from settings.Certificates Certs map[types.NamespacedName]*corev1.Secret // RequestParams is a secret from Settings.IdentityProvider.RequestParams diff --git a/pomerium/config.go b/pomerium/config.go index 7d9018ba..4fe5de32 100644 --- a/pomerium/config.go +++ b/pomerium/config.go @@ -1,10 +1,13 @@ package pomerium import ( + "bytes" "context" + "encoding/base64" "fmt" "net/url" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" corev1 "k8s.io/api/core/v1" @@ -28,6 +31,7 @@ func applyConfig(ctx context.Context, p *pb.Config, c *model.Config) error { name string fn func(context.Context, *pb.Config, *model.Config) error }{ + {"ca", applyCertificateAuthority}, {"certs", applyCerts}, {"authenticate", applyAuthenticate}, {"idp", applyIDP}, @@ -79,6 +83,22 @@ func applyCookie(_ context.Context, p *pb.Config, c *model.Config) error { return nil } +func applyCertificateAuthority(ctx context.Context, p *pb.Config, c *model.Config) error { + if len(c.CASecrets) == 0 { + return nil + } + + var buf bytes.Buffer + + for _, secret := range c.CASecrets { + buf.Write(secret.Data[model.CAKey]) + buf.WriteRune('\n') + } + + p.Settings.CertificateAuthority = proto.String(base64.StdEncoding.EncodeToString(buf.Bytes())) + return nil +} + func applyCerts(_ context.Context, p *pb.Config, c *model.Config) error { if len(c.Certs) != len(c.Spec.Certificates) { return fmt.Errorf("expected %d cert secrets, only %d was fetched. this is a bug", len(c.Spec.Certificates), len(c.Certs)) diff --git a/pomerium/ctrl/run.go b/pomerium/ctrl/run.go index 3e99cfaf..758971cb 100644 --- a/pomerium/ctrl/run.go +++ b/pomerium/ctrl/run.go @@ -14,9 +14,7 @@ import ( "github.com/pomerium/ingress-controller/pomerium" ) -var ( - _ = pomerium.ConfigReconciler(new(Runner)) -) +var _ = pomerium.ConfigReconciler(new(Runner)) // Runner implements pomerium control loop type Runner struct {