From 8d12c1b67412fe1a3173ecec90a5d20ed1fc90a6 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Thu, 24 Mar 2022 15:46:10 -0700 Subject: [PATCH 01/10] HTTP listener: default disabled and may only bind to loopback interfaces --- Dockerfile | 2 +- deploy/supervisor/deployment.yaml | 4 +- deploy/supervisor/values.yaml | 33 +++---- internal/config/supervisor/config.go | 52 ++++++++++- internal/config/supervisor/config_test.go | 93 +++++++++++++++++-- .../docs/howto/configure-supervisor.md | 24 ++--- .../concierge-and-supervisor-demo.md | 2 +- 7 files changed, 165 insertions(+), 45 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5588ff77..c5087fee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ FROM gcr.io/distroless/static:nonroot@sha256:80c956fb0836a17a565c43a4026c9c80b20 COPY --from=build-env /usr/local/bin /usr/local/bin # Document the default server ports for the various server apps -EXPOSE 8080 8443 8444 10250 +EXPOSE 8443 8444 10250 # Run as non-root for security posture # Use the same non-root user as https://github.com/GoogleContainerTools/distroless/blob/fc3c4eaceb0518900f886aae90407c43be0a42d9/base/base.bzl#L9 diff --git a/deploy/supervisor/deployment.yaml b/deploy/supervisor/deployment.yaml index 1bd49903..b4c60ec2 100644 --- a/deploy/supervisor/deployment.yaml +++ b/deploy/supervisor/deployment.yaml @@ -1,4 +1,4 @@ -#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved. #! SPDX-License-Identifier: Apache-2.0 #@ load("@ytt:data", "data") @@ -115,8 +115,6 @@ spec: readOnly: false #! writable to allow for socket use #@ end ports: - - containerPort: 8080 - protocol: TCP - containerPort: 8443 protocol: TCP env: diff --git a/deploy/supervisor/values.yaml b/deploy/supervisor/values.yaml index 9474da11..e22d0306 100644 --- a/deploy/supervisor/values.yaml +++ b/deploy/supervisor/values.yaml @@ -1,4 +1,4 @@ -#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved. #! SPDX-License-Identifier: Apache-2.0 #@data/values @@ -74,17 +74,17 @@ api_group_suffix: pinniped.dev https_proxy: #! e.g. http://proxy.example.com no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local" #! do not proxy Kubernetes endpoints -#! Control the https and http listeners of the Supervisor. +#! Control the HTTP and HTTPS listeners of the Supervisor. #! #! The schema of this config is as follows: #! #! endpoints: #! https: #! network: tcp | unix | disabled -#! address: interface:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix +#! address: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix #! http: #! network: same as above -#! address: same as above +#! address: same as above, except that when network=tcp then the address is only allowed to bind to loopback interfaces #! #! Setting network to disabled turns off that particular listener. #! See https://pkg.go.dev/net#Listen and https://pkg.go.dev/net#Dial for a description of what can be @@ -98,23 +98,20 @@ no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,. #! network: tcp #! address: :8443 #! http: -#! network: tcp -#! address: :8080 +#! network: disabled #! -#! These defaults mean: bind to all interfaces using TCP. Use port 8443 for https and 8080 for http. -#! The defaults will change over time. Users should explicitly set this value if they wish to avoid -#! any changes on upgrade. +#! These defaults mean: For HTTPS listening, bind to all interfaces using TCP on port 8443. +#! Disable HTTP listening by default. #! -#! A future version of the Supervisor app may include a breaking change to adjust the default -#! behavior of the http listener to only listen on 127.0.0.1 (or perhaps even to be disabled). +#! The HTTP listener can only be bound to loopback interfaces. This allows the listener to accept +#! traffic from within the pod, e.g. from a service mesh sidecar. The HTTP listener should not be +#! used to accept traffic from outside the pod, since that would mean that the network traffic could be +#! transmitted unencrypted. The HTTPS listener should be used instead to accept traffic from outside the pod. +#! Ingresses and load balancers that terminate TLS connections should re-encrypt the data and route traffic +#! to the HTTPS listener. Unix domain sockets may also be used for integrations with service meshes. #! -#! Binding the http listener to addresses other than 127.0.0.1 or ::1 is deprecated. -#! -#! Unix domain sockets are recommended for integrations with service meshes. Ingresses that terminate -#! TLS connections at the edge should re-encrypt the data and route traffic to the https listener. -#! -#! Changing the port numbers used must be accompanied with matching changes to the service and deployment -#! manifests. Changes to the https listener must be coordinated with the deployment health checks. +#! Changing the HTTPS port number must be accompanied by matching changes to the service and deployment +#! manifests. Changes to the HTTPS listener must be coordinated with the deployment health checks. #! #! Optional. endpoints: diff --git a/internal/config/supervisor/config.go b/internal/config/supervisor/config.go index 1118c0ec..3e8412f3 100644 --- a/internal/config/supervisor/config.go +++ b/internal/config/supervisor/config.go @@ -1,4 +1,4 @@ -// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // Package supervisor contains functionality to load/store Config's from/to @@ -8,6 +8,7 @@ package supervisor import ( "fmt" "io/ioutil" + "net" "strings" "k8s.io/utils/pointer" @@ -66,8 +67,7 @@ func FromPath(path string) (*Config, error) { Address: ":8443", }) maybeSetEndpointDefault(&config.Endpoints.HTTP, Endpoint{ - Network: NetworkTCP, - Address: ":8080", + Network: NetworkDisabled, }) if err := validateEndpoint(*config.Endpoints.HTTPS); err != nil { @@ -76,6 +76,9 @@ func FromPath(path string) (*Config, error) { if err := validateEndpoint(*config.Endpoints.HTTP); err != nil { return nil, fmt.Errorf("validate http endpoint: %w", err) } + if err := validateAdditionalHTTPEndpointRequirements(*config.Endpoints.HTTP); err != nil { + return nil, fmt.Errorf("validate http endpoint: %w", err) + } if err := validateAtLeastOneEnabledEndpoint(*config.Endpoints.HTTPS, *config.Endpoints.HTTP); err != nil { return nil, fmt.Errorf("validate endpoints: %w", err) } @@ -128,6 +131,16 @@ func validateEndpoint(endpoint Endpoint) error { } } +func validateAdditionalHTTPEndpointRequirements(endpoint Endpoint) error { + if endpoint.Network == NetworkTCP && !addrIsOnlyOnLoopback(endpoint.Address) { + return fmt.Errorf( + "http listener address %q for %q network may only bind to loopback interfaces", + endpoint.Address, + endpoint.Network) + } + return nil +} + func validateAtLeastOneEnabledEndpoint(endpoints ...Endpoint) error { for _, endpoint := range endpoints { if endpoint.Network != NetworkDisabled { @@ -136,3 +149,36 @@ func validateAtLeastOneEnabledEndpoint(endpoints ...Endpoint) error { } return constable.Error("all endpoints are disabled") } + +// For tcp networks, the address can be in several formats: host:port, host:, and :port. +// See address description in https://pkg.go.dev/net#Listen and https://pkg.go.dev/net#Dial. +// The host may be a literal IP address, or a host name that can be resolved to IP addresses, +// or a literal unspecified IP address (as in "0.0.0.0:80" or "[::]:80"), or empty. +// If the host is a literal IPv6 address it must be enclosed in square brackets, as in "[2001:db8::1]:80" or +// "[fe80::1%zone]:80". The zone specifies the scope of the literal IPv6 address as defined in RFC 4007. +// The port may be a literal port number or a service name, the value 0, or empty. +// Returns true if a net.Listen listener at this address would only listen on loopback interfaces. +// Returns false if the listener would listen on any non-loopback interfaces, or when called with illegal input. +func addrIsOnlyOnLoopback(addr string) bool { + // First try parsing as a `host:port`. net.SplitHostPort allows empty host and empty port. + host, _, err := net.SplitHostPort(addr) + if err != nil { + // Illegal input. + return false + } + if host == "" { + // Input was :port. This would bind to all interfaces, so it is not only on loopback. + return false + } + if host == "localhost" { + // This is only on loopback. + return true + } + // The host could be a hostname, an IPv4 address, or an IPv6 address. + ip := net.ParseIP(host) + if ip == nil { + // The address was not an IP. It must have been some hostname other than "localhost". + return false + } + return ip.IsLoopback() +} diff --git a/internal/config/supervisor/config_test.go b/internal/config/supervisor/config_test.go index 3953238e..285867b4 100644 --- a/internal/config/supervisor/config_test.go +++ b/internal/config/supervisor/config_test.go @@ -1,16 +1,16 @@ -// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package supervisor import ( + "fmt" "io/ioutil" "os" "testing" - "k8s.io/utils/pointer" - "github.com/stretchr/testify/require" + "k8s.io/utils/pointer" "go.pinniped.dev/internal/here" ) @@ -37,7 +37,8 @@ func TestFromPath(t *testing.T) { network: unix address: :1234 http: - network: disabled + network: tcp + address: 127.0.0.1:1234 `), wantConfig: &Config{ APIGroupSuffix: pointer.StringPtr("some.suffix.com"), @@ -54,7 +55,8 @@ func TestFromPath(t *testing.T) { Address: ":1234", }, HTTP: &Endpoint{ - Network: "disabled", + Network: "tcp", + Address: "127.0.0.1:1234", }, }, }, @@ -78,8 +80,7 @@ func TestFromPath(t *testing.T) { Address: ":8443", }, HTTP: &Endpoint{ - Network: "tcp", - Address: ":8080", + Network: "disabled", }, }, }, @@ -126,6 +127,21 @@ func TestFromPath(t *testing.T) { `), wantError: `validate http endpoint: unknown network "bar"`, }, + { + name: "http endpoint uses tcp but binds to more than only loopback interfaces", + yaml: here.Doc(` + --- + names: + defaultTLSCertificateSecret: my-secret-name + endpoints: + https: + network: disabled + http: + network: tcp + address: :8080 + `), + wantError: `validate http endpoint: http listener address ":8080" for "tcp" network may only bind to loopback interfaces`, + }, { name: "endpoint disabled with non-empty address", yaml: here.Doc(` @@ -208,3 +224,66 @@ func TestFromPath(t *testing.T) { }) } } + +func TestAddrIsOnlyOnLoopback(t *testing.T) { + tests := []struct { + addr string + want bool + }{ + {addr: "localhost:", want: true}, + {addr: "localhost:0", want: true}, + {addr: "localhost:80", want: true}, + {addr: "localhost:http", want: true}, + {addr: "127.0.0.1:", want: true}, + {addr: "127.0.0.1:0", want: true}, + {addr: "127.0.0.1:80", want: true}, + {addr: "127.0.0.1:http", want: true}, + {addr: "[::1]:", want: true}, + {addr: "[::1]:0", want: true}, + {addr: "[::1]:80", want: true}, + {addr: "[::1]:http", want: true}, + {addr: "[0:0:0:0:0:0:0:1]:", want: true}, + {addr: "[0:0:0:0:0:0:0:1]:0", want: true}, + {addr: "[0:0:0:0:0:0:0:1]:80", want: true}, + {addr: "[0:0:0:0:0:0:0:1]:http", want: true}, + {addr: "", want: false}, // illegal input, can't be empty + {addr: "host", want: false}, // illegal input, need colon + {addr: "localhost", want: false}, // illegal input, need colon + {addr: "127.0.0.1", want: false}, // illegal input, need colon + {addr: ":", want: false}, // illegal input, need either host or port + {addr: "2001:db8::1:80", want: false}, // illegal input, forgot square brackets + {addr: ":0", want: false}, + {addr: ":80", want: false}, + {addr: ":http", want: false}, + {addr: "notlocalhost:", want: false}, + {addr: "notlocalhost:0", want: false}, + {addr: "notlocalhost:80", want: false}, + {addr: "notlocalhost:http", want: false}, + {addr: "0.0.0.0:", want: false}, + {addr: "0.0.0.0:0", want: false}, + {addr: "0.0.0.0:80", want: false}, + {addr: "0.0.0.0:http", want: false}, + {addr: "[::]:", want: false}, + {addr: "[::]:0", want: false}, + {addr: "[::]:80", want: false}, + {addr: "[::]:http", want: false}, + {addr: "42.42.42.42:", want: false}, + {addr: "42.42.42.42:0", want: false}, + {addr: "42.42.42.42:80", want: false}, + {addr: "42.42.42.42:http", want: false}, + {addr: "[2001:db8::1]:", want: false}, + {addr: "[2001:db8::1]:0", want: false}, + {addr: "[2001:db8::1]:80", want: false}, + {addr: "[2001:db8::1]:http", want: false}, + {addr: "[fe80::1%zone]:", want: false}, + {addr: "[fe80::1%zone]:0", want: false}, + {addr: "[fe80::1%zone]:80", want: false}, + {addr: "[fe80::1%zone]:http", want: false}, + } + for _, test := range tests { + tt := test + t.Run(fmt.Sprintf("address %s should be %t", tt.addr, tt.want), func(t *testing.T) { + require.Equal(t, tt.want, addrIsOnlyOnLoopback(tt.addr)) + }) + } +} diff --git a/site/content/docs/howto/configure-supervisor.md b/site/content/docs/howto/configure-supervisor.md index b6daf592..cfbee2cf 100644 --- a/site/content/docs/howto/configure-supervisor.md +++ b/site/content/docs/howto/configure-supervisor.md @@ -46,26 +46,26 @@ The most common ways are: configured with TLS certificates and will terminate the TLS connection itself (see the section about FederationDomain below). The LoadBalancer Service should be configured to use the HTTPS port 443 of the Supervisor pods as its `targetPort`. - *Warning:* Never expose the Supervisor's HTTP port 8080 to the public. It would not be secure for the OIDC protocol - to use HTTP, because the user's secret OIDC tokens would be transmitted across the network without encryption. - - Or, define an [Ingress resource](https://kubernetes.io/docs/concepts/services-networking/ingress/). In this case, the [Ingress typically terminates TLS](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) - and then talks plain HTTP to its backend, - which would be a NodePort or LoadBalancer Service in front of the HTTP port 8080 of the Supervisor pods. - However, because the Supervisor's endpoints deal with sensitive credentials, it is much better if the - traffic is encrypted using TLS all the way into the Supervisor's Pods. Some Ingress implementations - may support re-encrypting the traffic before sending it to the backend. If your Ingress controller does not - support this, then consider using one of the other configurations described here instead of using an Ingress. + and then talks plain HTTP to its backend. + However, because the Supervisor's endpoints deal with sensitive credentials, the ingress must be configured to re-encrypt + traffic using TLS on the backend (upstream) into the Supervisor's Pods. It would not be secure for the OIDC protocol + to use HTTP, because the user's secret OIDC tokens would be transmitted across the network without encryption. + If your Ingress controller does not support this feature, then consider using one of the other configurations + described here instead of using an Ingress. The backend of the Ingress would typically point to a NodePort or + LoadBalancer Service which exposes the HTTPS port 8443 of the Supervisor pods. The required configuration of the Ingress is specific to your cluster's Ingress Controller, so please refer to the documentation from your Kubernetes provider. If you are using a cluster from a cloud provider, then you'll probably want to start with that provider's documentation. For example, if your cluster is a Google GKE cluster, refer to - the [GKE documentation for Ingress](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress). + the [GKE documentation for Ingress](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress) and the + [GKE documentation for enabling TLS on the backend of an Ingress](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress-xlb#https_tls_between_load_balancer_and_your_application). Otherwise, the Kubernetes documentation provides a list of popular [Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), including - [Contour](https://projectcontour.io/) and many others. + [Contour](https://projectcontour.io/) and many others. Contour is an example of an ingress implementation which + [supports TLS on the backend](https://projectcontour.io/docs/main/config/upstream-tls/). - Or, expose the Supervisor app using a Kubernetes service mesh technology (e.g. [Istio](https://istio.io/)). @@ -133,7 +133,7 @@ spec: ports: - protocol: TCP port: 443 - targetPort: 8443 # 8443 is the TLS port. Do not expose port 8080. + targetPort: 8443 # 8443 is the TLS port. ``` ### Example: Creating a NodePort Service diff --git a/site/content/docs/tutorials/concierge-and-supervisor-demo.md b/site/content/docs/tutorials/concierge-and-supervisor-demo.md index 33cab765..5131aba1 100644 --- a/site/content/docs/tutorials/concierge-and-supervisor-demo.md +++ b/site/content/docs/tutorials/concierge-and-supervisor-demo.md @@ -218,7 +218,7 @@ spec: ports: - protocol: TCP port: 443 - targetPort: 8443 # 8443 is the TLS port. Do not expose port 8080. + targetPort: 8443 # 8443 is the TLS port. EOF ``` From 488f08dd6e07f96c597f576c34b19d77f963037d Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Mon, 28 Mar 2022 17:03:23 -0700 Subject: [PATCH 02/10] Provide a way to override the new HTTP loopback-only validation Add new deprecated_insecure_accept_external_unencrypted_http_requests value in values.yaml. Allow it to be a boolean or a string to make it easier to use (both --data-value and --data-value-yaml will work). Also: - Consider "ip6-localhost" and "ip6-loopback" to be loopback addresses for the validation - Remove unused env.SupervisorHTTPAddress var - Deprecate the `service_http_*` values in values.yaml by renaming them and causing a ytt render error when the old names are used --- deploy/supervisor/helpers.lib.yaml | 3 +- deploy/supervisor/service.yaml | 37 ++++-- deploy/supervisor/values.yaml | 40 +++++-- hack/lib/kind-config/single-node.yaml | 7 -- hack/prepare-for-integration-tests.sh | 10 +- internal/config/supervisor/config.go | 17 ++- internal/config/supervisor/config_test.go | 107 +++++++++++++++++- internal/config/supervisor/types.go | 13 ++- .../docs/howto/configure-supervisor.md | 10 +- test/testlib/env.go | 8 +- 10 files changed, 191 insertions(+), 61 deletions(-) diff --git a/deploy/supervisor/helpers.lib.yaml b/deploy/supervisor/helpers.lib.yaml index ebe44045..33a6bfdd 100644 --- a/deploy/supervisor/helpers.lib.yaml +++ b/deploy/supervisor/helpers.lib.yaml @@ -1,4 +1,4 @@ -#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved. #! SPDX-License-Identifier: Apache-2.0 #@ load("@ytt:data", "data") @@ -52,6 +52,7 @@ _: #@ template.replace(data.values.custom_labels) #@ "defaultTLSCertificateSecret": defaultResourceNameWithSuffix("default-tls-certificate"), #@ }, #@ "labels": labels(), +#@ "insecure_accept_external_unencrypted_http_requests": data.values.deprecated_insecure_accept_external_unencrypted_http_requests #@ } #@ if data.values.log_level: #@ config["logLevel"] = getAndValidateLogLevel() diff --git a/deploy/supervisor/service.yaml b/deploy/supervisor/service.yaml index b07fbd9c..a64ac028 100644 --- a/deploy/supervisor/service.yaml +++ b/deploy/supervisor/service.yaml @@ -1,10 +1,23 @@ -#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved. #! SPDX-License-Identifier: Apache-2.0 #@ load("@ytt:data", "data") #@ load("helpers.lib.yaml", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix") -#@ if data.values.service_http_nodeport_port or data.values.service_https_nodeport_port: +#@ if data.values.service_http_nodeport_port != "removed": +#@ fail("value service_http_nodeport_port has been renamed to deprecated_service_http_nodeport_port and will be removed in a future release") +#@ end +#@ if data.values.service_http_nodeport_nodeport != "removed": +#@ fail("value service_http_nodeport_nodeport has been renamed to deprecated_service_http_nodeport_nodeport and will be removed in a future release") +#@ end +#@ if data.values.service_http_loadbalancer_port != "removed": +#@ fail("value service_http_loadbalancer_port has been renamed to deprecated_service_http_loadbalancer_port and will be removed in a future release") +#@ end +#@ if data.values.service_http_clusterip_port != "removed": +#@ fail("value service_http_clusterip_port has been renamed to deprecated_service_http_clusterip_port and will be removed in a future release") +#@ end + +#@ if data.values.deprecated_service_http_nodeport_port or data.values.service_https_nodeport_port: --- apiVersion: v1 kind: Service @@ -19,13 +32,13 @@ spec: type: NodePort selector: #@ deploymentPodLabel() ports: - #@ if data.values.service_http_nodeport_port: + #@ if data.values.deprecated_service_http_nodeport_port: - name: http protocol: TCP - port: #@ data.values.service_http_nodeport_port + port: #@ data.values.deprecated_service_http_nodeport_port targetPort: 8080 - #@ if data.values.service_http_nodeport_nodeport: - nodePort: #@ data.values.service_http_nodeport_nodeport + #@ if data.values.deprecated_service_http_nodeport_nodeport: + nodePort: #@ data.values.deprecated_service_http_nodeport_nodeport #@ end #@ end #@ if data.values.service_https_nodeport_port: @@ -39,7 +52,7 @@ spec: #@ end #@ end -#@ if data.values.service_http_clusterip_port or data.values.service_https_clusterip_port: +#@ if data.values.deprecated_service_http_clusterip_port or data.values.service_https_clusterip_port: --- apiVersion: v1 kind: Service @@ -54,10 +67,10 @@ spec: type: ClusterIP selector: #@ deploymentPodLabel() ports: - #@ if data.values.service_http_clusterip_port: + #@ if data.values.deprecated_service_http_clusterip_port: - name: http protocol: TCP - port: #@ data.values.service_http_clusterip_port + port: #@ data.values.deprecated_service_http_clusterip_port targetPort: 8080 #@ end #@ if data.values.service_https_clusterip_port: @@ -68,7 +81,7 @@ spec: #@ end #@ end -#@ if data.values.service_http_loadbalancer_port or data.values.service_https_loadbalancer_port: +#@ if data.values.deprecated_service_http_loadbalancer_port or data.values.service_https_loadbalancer_port: --- apiVersion: v1 kind: Service @@ -86,10 +99,10 @@ spec: loadBalancerIP: #@ data.values.service_loadbalancer_ip #@ end ports: - #@ if data.values.service_http_loadbalancer_port: + #@ if data.values.deprecated_service_http_loadbalancer_port: - name: http protocol: TCP - port: #@ data.values.service_http_loadbalancer_port + port: #@ data.values.deprecated_service_http_loadbalancer_port targetPort: 8080 #@ end #@ if data.values.service_https_loadbalancer_port: diff --git a/deploy/supervisor/values.yaml b/deploy/supervisor/values.yaml index e22d0306..6a87dce6 100644 --- a/deploy/supervisor/values.yaml +++ b/deploy/supervisor/values.yaml @@ -35,26 +35,31 @@ image_tag: latest #! Optional. image_pull_dockerconfigjson: #! e.g. {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}} -#! Specify how to expose the Supervisor app's HTTP and/or HTTPS ports as a Service. -#! Typically you would set a value for only one of the following service types, for either HTTP or HTTPS depending on your needs. -#! An HTTP service should not be exposed outside the cluster. It would not be secure to serve OIDC endpoints to end users via HTTP. -#! Setting any of these values means that a Service of that type will be created. +#! Specify how to expose the Supervisor app's HTTPS port as a Service. +#! Typically, you would set a value for only one of the following service types. +#! Setting any of these values means that a Service of that type will be created. They are all optional. #! Note that all port numbers should be numbers (not strings), i.e. use ytt's `--data-value-yaml` instead of `--data-value`. -service_http_nodeport_port: #! when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234 -service_http_nodeport_nodeport: #! the `nodePort` value of the NodePort Service, optional when `service_http_nodeport_port` is specified; e.g. 31234 -service_http_loadbalancer_port: #! when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443 -service_http_clusterip_port: #! when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443 +#! Several of these values have been deprecated and will be removed in a future release. Their names have been changed to +#! mark them as deprecated and to make it obvious upon upgrade to anyone who was using them that they have been deprecated. +service_http_nodeport_port: removed #! this value has been deprecated and renamed to deprecated_service_http_nodeport_port; will be removed in a future release +service_http_nodeport_nodeport: removed #! this value has been deprecated and renamed to deprecated_service_http_nodeport_nodeport; will be removed in a future release +service_http_loadbalancer_port: removed #! this value has been deprecated and renamed to deprecated_service_http_loadbalancer_port; will be removed in a future release +service_http_clusterip_port: removed #! this value has been deprecated and renamed to deprecated_service_http_clusterip_port; will be removed in a future release +deprecated_service_http_nodeport_port: #! will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234 +deprecated_service_http_nodeport_nodeport: #! will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234 +deprecated_service_http_loadbalancer_port: #! will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443 +deprecated_service_http_clusterip_port: #! will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443 service_https_nodeport_port: #! when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243 -service_https_nodeport_nodeport: #! the `nodePort` value of the NodePort Service, optional when `service_http_nodeport_port` is specified; e.g. 31243 +service_https_nodeport_nodeport: #! the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243 service_https_loadbalancer_port: #! when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443 service_https_clusterip_port: #! when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443 #! The `loadBalancerIP` value of the LoadBalancer Service. -#! Ignored unless service_http_loadbalancer_port and/or service_https_loadbalancer_port are provided. +#! Ignored unless service_https_loadbalancer_port is provided. #! Optional. service_loadbalancer_ip: #! e.g. 1.2.3.4 -#! Specify the verbosity of logging: info ("nice to know" information), debug (developer -#! information), trace (timing information), all (kitchen sink). +#! Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), +#! or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged. log_level: #! By default, when this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs. run_as_user: 65532 #! run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice @@ -115,3 +120,14 @@ no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,. #! #! Optional. endpoints: + +#! Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used. +#! When deprecated_insecure_accept_external_unencrypted_http_requests is true, the HTTP listener is allowed to bind to any +#! interface, including interfaces that are listening for traffic from outside the pod. This value is being introduced +#! to ease the transition to the new loopback interface validation for the HTTP port for any users who need more time +#! to change their ingress strategy to avoid using plain HTTP into the Supervisor pods. +#! This value is being introduced and immediately deprecated. It will be removed in some future release, at which time +#! traffic from outside the pod will need to be sent to the HTTPS listener instead, with no simple workaround available. +#! Allowed values are true (boolean), "true" (string), false (boolean), and "false" (string). The default is false. +#! Optional. +deprecated_insecure_accept_external_unencrypted_http_requests: false diff --git a/hack/lib/kind-config/single-node.yaml b/hack/lib/kind-config/single-node.yaml index ac90bfcb..f7178508 100644 --- a/hack/lib/kind-config/single-node.yaml +++ b/hack/lib/kind-config/single-node.yaml @@ -10,13 +10,6 @@ nodes: containerPort: 31243 hostPort: 12344 listenAddress: 127.0.0.1 - - protocol: TCP - # This same port number is hardcoded in the integration test setup - # when creating a Service on a kind cluster. It is used to talk to - # the supervisor app via HTTP. - containerPort: 31234 - hostPort: 12345 - listenAddress: 127.0.0.1 - protocol: TCP # This same port number is hardcoded in the integration test setup # when creating a Service on a kind cluster. It is used to talk to diff --git a/hack/prepare-for-integration-tests.sh b/hack/prepare-for-integration-tests.sh index 5d74f98f..e9116cd9 100755 --- a/hack/prepare-for-integration-tests.sh +++ b/hack/prepare-for-integration-tests.sh @@ -187,7 +187,7 @@ fi log_note "Checking for running kind cluster..." if ! kind get clusters | grep -q -e '^pinniped$'; then log_note "Creating a kind cluster..." - # Our kind config exposes node port 31234 as 127.0.0.1:12345, 31243 as 127.0.0.1:12344, and 31235 as 127.0.0.1:12346 + # Our kind config exposes node port 31243 as 127.0.0.1:12344 and 31235 as 127.0.0.1:12346 ./hack/kind-up.sh else if ! kubectl cluster-info | grep -E '(master|control plane)' | grep -q 127.0.0.1; then @@ -290,8 +290,6 @@ supervisor_app_name="pinniped-supervisor" supervisor_namespace="supervisor" supervisor_custom_labels="{mySupervisorCustomLabelName: mySupervisorCustomLabelValue}" log_level="debug" -service_http_nodeport_port="80" -service_http_nodeport_nodeport="31234" service_https_nodeport_port="443" service_https_nodeport_nodeport="31243" service_https_clusterip_port="443" @@ -311,15 +309,10 @@ else --data-value "image_tag=$tag" \ --data-value "log_level=$log_level" \ --data-value-yaml "custom_labels=$supervisor_custom_labels" \ - --data-value-yaml "service_http_nodeport_port=$service_http_nodeport_port" \ - --data-value-yaml "service_http_nodeport_nodeport=$service_http_nodeport_nodeport" \ --data-value-yaml "service_https_nodeport_port=$service_https_nodeport_port" \ --data-value-yaml "service_https_nodeport_nodeport=$service_https_nodeport_nodeport" \ --data-value-yaml "service_https_clusterip_port=$service_https_clusterip_port" \ >"$manifest" - # example of how to disable the http endpoint - # this is left enabled for now because our integration tests still rely on it - # --data-value-yaml 'endpoints={"http": {"network": "disabled"}}' \ kapp deploy --yes --app "$supervisor_app_name" --diff-changes --file "$manifest" kubectl apply --dry-run=client -f "$manifest" # Validate manifest schema. @@ -392,7 +385,6 @@ export PINNIPED_TEST_WEBHOOK_CA_BUNDLE=${webhook_ca_bundle} export PINNIPED_TEST_SUPERVISOR_NAMESPACE=${supervisor_namespace} export PINNIPED_TEST_SUPERVISOR_APP_NAME=${supervisor_app_name} export PINNIPED_TEST_SUPERVISOR_CUSTOM_LABELS='${supervisor_custom_labels}' -export PINNIPED_TEST_SUPERVISOR_HTTP_ADDRESS="127.0.0.1:12345" export PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS="localhost:12344" export PINNIPED_TEST_PROXY=http://127.0.0.1:12346 export PINNIPED_TEST_LDAP_HOST=ldap.tools.svc.cluster.local diff --git a/internal/config/supervisor/config.go b/internal/config/supervisor/config.go index 3e8412f3..d83ce294 100644 --- a/internal/config/supervisor/config.go +++ b/internal/config/supervisor/config.go @@ -76,7 +76,7 @@ func FromPath(path string) (*Config, error) { if err := validateEndpoint(*config.Endpoints.HTTP); err != nil { return nil, fmt.Errorf("validate http endpoint: %w", err) } - if err := validateAdditionalHTTPEndpointRequirements(*config.Endpoints.HTTP); err != nil { + if err := validateAdditionalHTTPEndpointRequirements(*config.Endpoints.HTTP, config.AllowExternalHTTP); err != nil { return nil, fmt.Errorf("validate http endpoint: %w", err) } if err := validateAtLeastOneEnabledEndpoint(*config.Endpoints.HTTPS, *config.Endpoints.HTTP); err != nil { @@ -131,8 +131,16 @@ func validateEndpoint(endpoint Endpoint) error { } } -func validateAdditionalHTTPEndpointRequirements(endpoint Endpoint) error { +func validateAdditionalHTTPEndpointRequirements(endpoint Endpoint, allowExternalHTTP string) error { if endpoint.Network == NetworkTCP && !addrIsOnlyOnLoopback(endpoint.Address) { + if allowExternalHTTP == "true" { + // Log that the validation should have been triggered. + plog.Warning("Listening on non-loopback interfaces for the HTTP port is deprecated and will be removed " + + "in a future release. Your current configuration would not be allowed in that future release. " + + "Please see comments in deploy/supervisor/values.yaml and review your settings.") + // Skip enforcement of the validation. + return nil + } return fmt.Errorf( "http listener address %q for %q network may only bind to loopback interfaces", endpoint.Address, @@ -170,8 +178,9 @@ func addrIsOnlyOnLoopback(addr string) bool { // Input was :port. This would bind to all interfaces, so it is not only on loopback. return false } - if host == "localhost" { - // This is only on loopback. + if host == "localhost" || host == "ip6-localhost" || host == "ip6-loopback" { + // These hostnames are documented as the loopback hostnames seen inside the pod's containers in + // https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/#default-hosts-file-content return true } // The host could be a hostname, an IPv4 address, or an IPv6 address. diff --git a/internal/config/supervisor/config_test.go b/internal/config/supervisor/config_test.go index 285867b4..f66ffb27 100644 --- a/internal/config/supervisor/config_test.go +++ b/internal/config/supervisor/config_test.go @@ -39,6 +39,7 @@ func TestFromPath(t *testing.T) { http: network: tcp address: 127.0.0.1:1234 + insecure_accept_external_unencrypted_http_requests: false `), wantConfig: &Config{ APIGroupSuffix: pointer.StringPtr("some.suffix.com"), @@ -59,6 +60,7 @@ func TestFromPath(t *testing.T) { Address: "127.0.0.1:1234", }, }, + AllowExternalHTTP: "false", }, }, { @@ -83,6 +85,7 @@ func TestFromPath(t *testing.T) { Network: "disabled", }, }, + AllowExternalHTTP: "", }, }, { @@ -128,7 +131,7 @@ func TestFromPath(t *testing.T) { wantError: `validate http endpoint: unknown network "bar"`, }, { - name: "http endpoint uses tcp but binds to more than only loopback interfaces", + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests missing", yaml: here.Doc(` --- names: @@ -142,6 +145,100 @@ func TestFromPath(t *testing.T) { `), wantError: `validate http endpoint: http listener address ":8080" for "tcp" network may only bind to loopback interfaces`, }, + { + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to boolean false", + yaml: here.Doc(` + --- + names: + defaultTLSCertificateSecret: my-secret-name + endpoints: + https: + network: disabled + http: + network: tcp + address: :8080 + insecure_accept_external_unencrypted_http_requests: false + `), + wantError: `validate http endpoint: http listener address ":8080" for "tcp" network may only bind to loopback interfaces`, + }, + { + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to string false", + yaml: here.Doc(` + --- + names: + defaultTLSCertificateSecret: my-secret-name + endpoints: + https: + network: disabled + http: + network: tcp + address: :8080 + insecure_accept_external_unencrypted_http_requests: "false" + `), + wantError: `validate http endpoint: http listener address ":8080" for "tcp" network may only bind to loopback interfaces`, + }, + { + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to boolean true", + yaml: here.Doc(` + --- + names: + defaultTLSCertificateSecret: my-secret-name + endpoints: + http: + network: tcp + address: :1234 + insecure_accept_external_unencrypted_http_requests: true + `), + wantConfig: &Config{ + APIGroupSuffix: pointer.StringPtr("pinniped.dev"), + Labels: map[string]string{}, + NamesConfig: NamesConfigSpec{ + DefaultTLSCertificateSecret: "my-secret-name", + }, + Endpoints: &Endpoints{ + HTTPS: &Endpoint{ + Network: "tcp", + Address: ":8443", + }, + HTTP: &Endpoint{ + Network: "tcp", + Address: ":1234", + }, + }, + AllowExternalHTTP: "true", + }, + }, + { + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to string true", + yaml: here.Doc(` + --- + names: + defaultTLSCertificateSecret: my-secret-name + endpoints: + http: + network: tcp + address: :1234 + insecure_accept_external_unencrypted_http_requests: "true" + `), + wantConfig: &Config{ + APIGroupSuffix: pointer.StringPtr("pinniped.dev"), + Labels: map[string]string{}, + NamesConfig: NamesConfigSpec{ + DefaultTLSCertificateSecret: "my-secret-name", + }, + Endpoints: &Endpoints{ + HTTPS: &Endpoint{ + Network: "tcp", + Address: ":8443", + }, + HTTP: &Endpoint{ + Network: "tcp", + Address: ":1234", + }, + }, + AllowExternalHTTP: "true", + }, + }, { name: "endpoint disabled with non-empty address", yaml: here.Doc(` @@ -234,6 +331,14 @@ func TestAddrIsOnlyOnLoopback(t *testing.T) { {addr: "localhost:0", want: true}, {addr: "localhost:80", want: true}, {addr: "localhost:http", want: true}, + {addr: "ip6-localhost:", want: true}, + {addr: "ip6-localhost:0", want: true}, + {addr: "ip6-localhost:80", want: true}, + {addr: "ip6-localhost:http", want: true}, + {addr: "ip6-loopback:", want: true}, + {addr: "ip6-loopback:0", want: true}, + {addr: "ip6-loopback:80", want: true}, + {addr: "ip6-loopback:http", want: true}, {addr: "127.0.0.1:", want: true}, {addr: "127.0.0.1:0", want: true}, {addr: "127.0.0.1:80", want: true}, diff --git a/internal/config/supervisor/types.go b/internal/config/supervisor/types.go index 9a4e6c21..f2cfc1f7 100644 --- a/internal/config/supervisor/types.go +++ b/internal/config/supervisor/types.go @@ -1,4 +1,4 @@ -// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package supervisor @@ -7,11 +7,12 @@ import "go.pinniped.dev/internal/plog" // Config contains knobs to setup an instance of the Pinniped Supervisor. type Config struct { - APIGroupSuffix *string `json:"apiGroupSuffix,omitempty"` - Labels map[string]string `json:"labels"` - NamesConfig NamesConfigSpec `json:"names"` - LogLevel plog.LogLevel `json:"logLevel"` - Endpoints *Endpoints `json:"endpoints"` + APIGroupSuffix *string `json:"apiGroupSuffix,omitempty"` + Labels map[string]string `json:"labels"` + NamesConfig NamesConfigSpec `json:"names"` + LogLevel plog.LogLevel `json:"logLevel"` + Endpoints *Endpoints `json:"endpoints"` + AllowExternalHTTP string `json:"insecure_accept_external_unencrypted_http_requests"` } // NamesConfigSpec configures the names of some Kubernetes resources for the Supervisor. diff --git a/site/content/docs/howto/configure-supervisor.md b/site/content/docs/howto/configure-supervisor.md index cfbee2cf..c4fc40fd 100644 --- a/site/content/docs/howto/configure-supervisor.md +++ b/site/content/docs/howto/configure-supervisor.md @@ -55,7 +55,11 @@ The most common ways are: to use HTTP, because the user's secret OIDC tokens would be transmitted across the network without encryption. If your Ingress controller does not support this feature, then consider using one of the other configurations described here instead of using an Ingress. The backend of the Ingress would typically point to a NodePort or - LoadBalancer Service which exposes the HTTPS port 8443 of the Supervisor pods. + LoadBalancer Service which exposes the HTTPS port 8443 of the Supervisor pods. (Using plain HTTP from the Ingress + to the Supervisor pods is deprecated and will be removed in a future release. To aid in transition, it may be enabled + using the `insecure_accept_external_unencrypted_http_requests` value in + [values.yaml](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/supervisor/values.yaml), + until that setting is removed in a future release.) The required configuration of the Ingress is specific to your cluster's Ingress Controller, so please refer to the documentation from your Kubernetes provider. If you are using a cluster from a cloud provider, then you'll probably @@ -65,7 +69,9 @@ The most common ways are: Otherwise, the Kubernetes documentation provides a list of popular [Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), including [Contour](https://projectcontour.io/) and many others. Contour is an example of an ingress implementation which - [supports TLS on the backend](https://projectcontour.io/docs/main/config/upstream-tls/). + [supports TLS on the backend](https://projectcontour.io/docs/main/config/upstream-tls/), + along with [TLS session proxying and TLS session pass-through](https://projectcontour.io/docs/main/config/tls-termination/) + as alternative ways to maintain TLS all the way to the backend service. - Or, expose the Supervisor app using a Kubernetes service mesh technology (e.g. [Istio](https://istio.io/)). diff --git a/test/testlib/env.go b/test/testlib/env.go index 18f9753c..693fea98 100644 --- a/test/testlib/env.go +++ b/test/testlib/env.go @@ -48,7 +48,6 @@ type TestEnv struct { KubernetesDistribution KubeDistro `json:"kubernetesDistribution"` Capabilities map[Capability]bool `json:"capabilities"` TestWebhook auth1alpha1.WebhookAuthenticatorSpec `json:"testWebhook"` - SupervisorHTTPAddress string `json:"supervisorHttpAddress"` SupervisorHTTPSAddress string `json:"supervisorHttpsAddress"` SupervisorHTTPSIngressAddress string `json:"supervisorHttpsIngressAddress"` SupervisorHTTPSIngressCABundle string `json:"supervisorHttpsIngressCABundle"` @@ -207,12 +206,7 @@ func loadEnvVars(t *testing.T, result *TestEnv) { result.SupervisorAppName = needEnv(t, "PINNIPED_TEST_SUPERVISOR_APP_NAME") result.TestWebhook.TLS = &auth1alpha1.TLSSpec{CertificateAuthorityData: needEnv(t, "PINNIPED_TEST_WEBHOOK_CA_BUNDLE")} - result.SupervisorHTTPAddress = os.Getenv("PINNIPED_TEST_SUPERVISOR_HTTP_ADDRESS") - result.SupervisorHTTPSIngressAddress = os.Getenv("PINNIPED_TEST_SUPERVISOR_HTTPS_INGRESS_ADDRESS") - require.NotEmptyf(t, - result.SupervisorHTTPAddress+result.SupervisorHTTPSIngressAddress, - "must specify either PINNIPED_TEST_SUPERVISOR_HTTP_ADDRESS or PINNIPED_TEST_SUPERVISOR_HTTPS_INGRESS_ADDRESS env var (or both) for integration tests", - ) + result.SupervisorHTTPSIngressAddress = needEnv(t, "PINNIPED_TEST_SUPERVISOR_HTTPS_INGRESS_ADDRESS") result.SupervisorHTTPSAddress = needEnv(t, "PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS") require.NotRegexp(t, "^[0-9]", result.SupervisorHTTPSAddress, "PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS must be a hostname with an optional port and cannot be an IP address", From 0e54ba1a20ee3a5e4c2555bab23d26d05969c801 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Tue, 29 Mar 2022 14:24:40 -0700 Subject: [PATCH 03/10] Slightly fancier way to prevent old values.yaml names from being used --- deploy/supervisor/service.yaml | 17 +++++++++-------- deploy/supervisor/values.yaml | 4 ---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/deploy/supervisor/service.yaml b/deploy/supervisor/service.yaml index a64ac028..fd6b9623 100644 --- a/deploy/supervisor/service.yaml +++ b/deploy/supervisor/service.yaml @@ -2,19 +2,20 @@ #! SPDX-License-Identifier: Apache-2.0 #@ load("@ytt:data", "data") +#@ load("@ytt:assert", "assert") #@ load("helpers.lib.yaml", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix") -#@ if data.values.service_http_nodeport_port != "removed": -#@ fail("value service_http_nodeport_port has been renamed to deprecated_service_http_nodeport_port and will be removed in a future release") +#@ if hasattr(data.values, "service_http_nodeport_port"): +#@ assert.fail('value "service_http_nodeport_port" has been renamed to "deprecated_service_http_nodeport_port" and will be removed in a future release') #@ end -#@ if data.values.service_http_nodeport_nodeport != "removed": -#@ fail("value service_http_nodeport_nodeport has been renamed to deprecated_service_http_nodeport_nodeport and will be removed in a future release") +#@ if hasattr(data.values, "service_http_nodeport_nodeport"): +#@ assert.fail('value "service_http_nodeport_nodeport" has been renamed to "deprecated_service_http_nodeport_nodeport" and will be removed in a future release') #@ end -#@ if data.values.service_http_loadbalancer_port != "removed": -#@ fail("value service_http_loadbalancer_port has been renamed to deprecated_service_http_loadbalancer_port and will be removed in a future release") +#@ if hasattr(data.values, "service_http_loadbalancer_port"): +#@ assert.fail('value "service_http_loadbalancer_port" has been renamed to "deprecated_service_http_loadbalancer_port" and will be removed in a future release') #@ end -#@ if data.values.service_http_clusterip_port != "removed": -#@ fail("value service_http_clusterip_port has been renamed to deprecated_service_http_clusterip_port and will be removed in a future release") +#@ if hasattr(data.values, "service_http_clusterip_port"): +#@ assert.fail('value "service_http_clusterip_port" has been renamed to "deprecated_service_http_clusterip_port" and will be removed in a future release') #@ end #@ if data.values.deprecated_service_http_nodeport_port or data.values.service_https_nodeport_port: diff --git a/deploy/supervisor/values.yaml b/deploy/supervisor/values.yaml index 6a87dce6..70e30672 100644 --- a/deploy/supervisor/values.yaml +++ b/deploy/supervisor/values.yaml @@ -41,10 +41,6 @@ image_pull_dockerconfigjson: #! e.g. {"auths":{"https://registry.example.com":{" #! Note that all port numbers should be numbers (not strings), i.e. use ytt's `--data-value-yaml` instead of `--data-value`. #! Several of these values have been deprecated and will be removed in a future release. Their names have been changed to #! mark them as deprecated and to make it obvious upon upgrade to anyone who was using them that they have been deprecated. -service_http_nodeport_port: removed #! this value has been deprecated and renamed to deprecated_service_http_nodeport_port; will be removed in a future release -service_http_nodeport_nodeport: removed #! this value has been deprecated and renamed to deprecated_service_http_nodeport_nodeport; will be removed in a future release -service_http_loadbalancer_port: removed #! this value has been deprecated and renamed to deprecated_service_http_loadbalancer_port; will be removed in a future release -service_http_clusterip_port: removed #! this value has been deprecated and renamed to deprecated_service_http_clusterip_port; will be removed in a future release deprecated_service_http_nodeport_port: #! will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234 deprecated_service_http_nodeport_nodeport: #! will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234 deprecated_service_http_loadbalancer_port: #! will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443 From 51c527a965a743f89347420e6a5fe075a59ef3f0 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Thu, 31 Mar 2022 16:23:45 -0700 Subject: [PATCH 04/10] Change to camel-case for insecureAcceptExternalUnencryptedHttpRequests - Use camel-case in the static configmap - Parse the value into a boolean in the go struct instead of a string - Add test for when unsupported value is used in the configmap - Run the config_test.go tests in parallel - Update some paragraphs in configure-supervisor.md for clarity --- deploy/supervisor/helpers.lib.yaml | 2 +- deploy/supervisor/values.yaml | 2 +- internal/config/supervisor/config.go | 4 +- internal/config/supervisor/config_test.go | 42 ++++++++++++------- internal/config/supervisor/types.go | 32 ++++++++++---- .../docs/howto/configure-supervisor.md | 38 +++++++++-------- 6 files changed, 77 insertions(+), 43 deletions(-) diff --git a/deploy/supervisor/helpers.lib.yaml b/deploy/supervisor/helpers.lib.yaml index 33a6bfdd..acd6d5a4 100644 --- a/deploy/supervisor/helpers.lib.yaml +++ b/deploy/supervisor/helpers.lib.yaml @@ -52,7 +52,7 @@ _: #@ template.replace(data.values.custom_labels) #@ "defaultTLSCertificateSecret": defaultResourceNameWithSuffix("default-tls-certificate"), #@ }, #@ "labels": labels(), -#@ "insecure_accept_external_unencrypted_http_requests": data.values.deprecated_insecure_accept_external_unencrypted_http_requests +#@ "insecureAcceptExternalUnencryptedHttpRequests": data.values.deprecated_insecure_accept_external_unencrypted_http_requests #@ } #@ if data.values.log_level: #@ config["logLevel"] = getAndValidateLogLevel() diff --git a/deploy/supervisor/values.yaml b/deploy/supervisor/values.yaml index 70e30672..e0fd50f3 100644 --- a/deploy/supervisor/values.yaml +++ b/deploy/supervisor/values.yaml @@ -122,7 +122,7 @@ endpoints: #! interface, including interfaces that are listening for traffic from outside the pod. This value is being introduced #! to ease the transition to the new loopback interface validation for the HTTP port for any users who need more time #! to change their ingress strategy to avoid using plain HTTP into the Supervisor pods. -#! This value is being introduced and immediately deprecated. It will be removed in some future release, at which time +#! This value is immediately deprecated upon its introduction. It will be removed in some future release, at which time #! traffic from outside the pod will need to be sent to the HTTPS listener instead, with no simple workaround available. #! Allowed values are true (boolean), "true" (string), false (boolean), and "false" (string). The default is false. #! Optional. diff --git a/internal/config/supervisor/config.go b/internal/config/supervisor/config.go index d83ce294..b7baadf8 100644 --- a/internal/config/supervisor/config.go +++ b/internal/config/supervisor/config.go @@ -131,9 +131,9 @@ func validateEndpoint(endpoint Endpoint) error { } } -func validateAdditionalHTTPEndpointRequirements(endpoint Endpoint, allowExternalHTTP string) error { +func validateAdditionalHTTPEndpointRequirements(endpoint Endpoint, allowExternalHTTP stringOrBoolAsBool) error { if endpoint.Network == NetworkTCP && !addrIsOnlyOnLoopback(endpoint.Address) { - if allowExternalHTTP == "true" { + if allowExternalHTTP { // Log that the validation should have been triggered. plog.Warning("Listening on non-loopback interfaces for the HTTP port is deprecated and will be removed " + "in a future release. Your current configuration would not be allowed in that future release. " + diff --git a/internal/config/supervisor/config_test.go b/internal/config/supervisor/config_test.go index f66ffb27..5d4d7a85 100644 --- a/internal/config/supervisor/config_test.go +++ b/internal/config/supervisor/config_test.go @@ -39,7 +39,7 @@ func TestFromPath(t *testing.T) { http: network: tcp address: 127.0.0.1:1234 - insecure_accept_external_unencrypted_http_requests: false + insecureAcceptExternalUnencryptedHttpRequests: false `), wantConfig: &Config{ APIGroupSuffix: pointer.StringPtr("some.suffix.com"), @@ -60,7 +60,7 @@ func TestFromPath(t *testing.T) { Address: "127.0.0.1:1234", }, }, - AllowExternalHTTP: "false", + AllowExternalHTTP: false, }, }, { @@ -85,7 +85,7 @@ func TestFromPath(t *testing.T) { Network: "disabled", }, }, - AllowExternalHTTP: "", + AllowExternalHTTP: false, }, }, { @@ -131,7 +131,7 @@ func TestFromPath(t *testing.T) { wantError: `validate http endpoint: unknown network "bar"`, }, { - name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests missing", + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecureAcceptExternalUnencryptedHttpRequests missing", yaml: here.Doc(` --- names: @@ -146,7 +146,7 @@ func TestFromPath(t *testing.T) { wantError: `validate http endpoint: http listener address ":8080" for "tcp" network may only bind to loopback interfaces`, }, { - name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to boolean false", + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecureAcceptExternalUnencryptedHttpRequests set to boolean false", yaml: here.Doc(` --- names: @@ -157,12 +157,22 @@ func TestFromPath(t *testing.T) { http: network: tcp address: :8080 - insecure_accept_external_unencrypted_http_requests: false + insecureAcceptExternalUnencryptedHttpRequests: false `), wantError: `validate http endpoint: http listener address ":8080" for "tcp" network may only bind to loopback interfaces`, }, { - name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to string false", + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecureAcceptExternalUnencryptedHttpRequests set to unsupported value", + yaml: here.Doc(` + --- + names: + defaultTLSCertificateSecret: my-secret-name + insecureAcceptExternalUnencryptedHttpRequests: "garbage" # this will be treated as the default, which is false + `), + wantError: `decode yaml: error unmarshaling JSON: while decoding JSON: invalid value for boolean`, + }, + { + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecureAcceptExternalUnencryptedHttpRequests set to string false", yaml: here.Doc(` --- names: @@ -173,12 +183,12 @@ func TestFromPath(t *testing.T) { http: network: tcp address: :8080 - insecure_accept_external_unencrypted_http_requests: "false" + insecureAcceptExternalUnencryptedHttpRequests: "false" `), wantError: `validate http endpoint: http listener address ":8080" for "tcp" network may only bind to loopback interfaces`, }, { - name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to boolean true", + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecureAcceptExternalUnencryptedHttpRequests set to boolean true", yaml: here.Doc(` --- names: @@ -187,7 +197,7 @@ func TestFromPath(t *testing.T) { http: network: tcp address: :1234 - insecure_accept_external_unencrypted_http_requests: true + insecureAcceptExternalUnencryptedHttpRequests: true `), wantConfig: &Config{ APIGroupSuffix: pointer.StringPtr("pinniped.dev"), @@ -205,11 +215,11 @@ func TestFromPath(t *testing.T) { Address: ":1234", }, }, - AllowExternalHTTP: "true", + AllowExternalHTTP: true, }, }, { - name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecure_accept_external_unencrypted_http_requests set to string true", + name: "http endpoint uses tcp but binds to more than only loopback interfaces with insecureAcceptExternalUnencryptedHttpRequests set to string true", yaml: here.Doc(` --- names: @@ -218,7 +228,7 @@ func TestFromPath(t *testing.T) { http: network: tcp address: :1234 - insecure_accept_external_unencrypted_http_requests: "true" + insecureAcceptExternalUnencryptedHttpRequests: "true" `), wantConfig: &Config{ APIGroupSuffix: pointer.StringPtr("pinniped.dev"), @@ -236,7 +246,7 @@ func TestFromPath(t *testing.T) { Address: ":1234", }, }, - AllowExternalHTTP: "true", + AllowExternalHTTP: true, }, }, { @@ -297,6 +307,8 @@ func TestFromPath(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { + t.Parallel() + // Write yaml to temp file f, err := ioutil.TempFile("", "pinniped-test-config-yaml-*") require.NoError(t, err) @@ -388,6 +400,8 @@ func TestAddrIsOnlyOnLoopback(t *testing.T) { for _, test := range tests { tt := test t.Run(fmt.Sprintf("address %s should be %t", tt.addr, tt.want), func(t *testing.T) { + t.Parallel() + require.Equal(t, tt.want, addrIsOnlyOnLoopback(tt.addr)) }) } diff --git a/internal/config/supervisor/types.go b/internal/config/supervisor/types.go index f2cfc1f7..e61d4068 100644 --- a/internal/config/supervisor/types.go +++ b/internal/config/supervisor/types.go @@ -3,16 +3,20 @@ package supervisor -import "go.pinniped.dev/internal/plog" +import ( + "errors" + + "go.pinniped.dev/internal/plog" +) // Config contains knobs to setup an instance of the Pinniped Supervisor. type Config struct { - APIGroupSuffix *string `json:"apiGroupSuffix,omitempty"` - Labels map[string]string `json:"labels"` - NamesConfig NamesConfigSpec `json:"names"` - LogLevel plog.LogLevel `json:"logLevel"` - Endpoints *Endpoints `json:"endpoints"` - AllowExternalHTTP string `json:"insecure_accept_external_unencrypted_http_requests"` + APIGroupSuffix *string `json:"apiGroupSuffix,omitempty"` + Labels map[string]string `json:"labels"` + NamesConfig NamesConfigSpec `json:"names"` + LogLevel plog.LogLevel `json:"logLevel"` + Endpoints *Endpoints `json:"endpoints"` + AllowExternalHTTP stringOrBoolAsBool `json:"insecureAcceptExternalUnencryptedHttpRequests"` } // NamesConfigSpec configures the names of some Kubernetes resources for the Supervisor. @@ -29,3 +33,17 @@ type Endpoint struct { Network string `json:"network"` Address string `json:"address"` } + +type stringOrBoolAsBool bool + +func (sb *stringOrBoolAsBool) UnmarshalJSON(b []byte) error { + switch string(b) { + case "true", `"true"`: + *sb = true + case "false", `"false"`: + *sb = false + default: + return errors.New("invalid value for boolean") + } + return nil +} diff --git a/site/content/docs/howto/configure-supervisor.md b/site/content/docs/howto/configure-supervisor.md index c4fc40fd..5f2c7e47 100644 --- a/site/content/docs/howto/configure-supervisor.md +++ b/site/content/docs/howto/configure-supervisor.md @@ -29,13 +29,17 @@ It is recommended that the traffic to these endpoints should be encrypted via TL Supervisor pods, even when crossing boundaries that are entirely inside the Kubernetes cluster. The credentials and tokens that are handled by these endpoints are too sensitive to transmit without encryption. -In all versions of the Supervisor app so far, there are both HTTP and HTTPS ports available for use by default. +In previous versions of the Supervisor app, there were both HTTP and HTTPS ports available for use by default. These ports each host all the Supervisor's endpoints. Unfortunately, this has caused some confusion in the community and some blog posts have been written which demonstrate using the HTTP port in such a way that a portion of the traffic's -path is unencrypted. **Anything which exposes the non-TLS HTTP port outside the Pod should be considered deprecated**. -A future version of the Supervisor app may include a breaking change to adjust the default behavior of the HTTP port -to only listen on 127.0.0.1 (or perhaps even to be disabled) to make it more clear that the Supervisor app is not intended -to receive non-TLS HTTP traffic from outside the Pod. +path is unencrypted. Newer versions of the Supervisor disable the HTTP port by default to make it more clear that +the Supervisor app is not intended to receive non-TLS HTTP traffic from outside the Pod. Furthermore, in these newer versions, +when the HTTP listener is configured to be enabled it may only listen on loopback interfaces for traffic from within its own pod. +To aid in transition for impacted users, the old behavior of allowing the HTTP listener to receive traffic from +outside the pod may be re-enabled using the +`deprecated_insecure_accept_external_unencrypted_http_requests` value in +[values.yaml](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/supervisor/values.yaml), +until that setting is removed in a future release. Because there are many ways to expose TLS services from a Kubernetes cluster, the Supervisor app leaves this up to the user. The most common ways are: @@ -54,12 +58,9 @@ The most common ways are: traffic using TLS on the backend (upstream) into the Supervisor's Pods. It would not be secure for the OIDC protocol to use HTTP, because the user's secret OIDC tokens would be transmitted across the network without encryption. If your Ingress controller does not support this feature, then consider using one of the other configurations - described here instead of using an Ingress. The backend of the Ingress would typically point to a NodePort or - LoadBalancer Service which exposes the HTTPS port 8443 of the Supervisor pods. (Using plain HTTP from the Ingress - to the Supervisor pods is deprecated and will be removed in a future release. To aid in transition, it may be enabled - using the `insecure_accept_external_unencrypted_http_requests` value in - [values.yaml](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/supervisor/values.yaml), - until that setting is removed in a future release.) + described here instead of using an Ingress. (Please refer to the paragraph above regarding the deprecation of the HTTP listener for more + information.) The backend of the Ingress would typically point to a NodePort or LoadBalancer Service which exposes + the HTTPS port 8443 of the Supervisor pods. The required configuration of the Ingress is specific to your cluster's Ingress Controller, so please refer to the documentation from your Kubernetes provider. If you are using a cluster from a cloud provider, then you'll probably @@ -81,24 +82,25 @@ The most common ways are: If your service mesh is capable of transparently encrypting traffic all the way into the Supervisor Pods, then you should use that capability. In this case, it may make sense to configure the Supervisor's - HTTP port to only listen on a Unix domain socket, such as when the service mesh injects a sidecar container that can - securely access the socket from within the same Pod. + HTTP port to listen on a Unix domain socket, such as when the service mesh injects a sidecar container that can + securely access the socket from within the same Pod. Alternatively, the HTTP port can be configured as a TCP listener + on loopback interfaces to receive traffic from sidecar containers. See the `endpoints` option in [deploy/supervisor/values.yml](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/supervisor/values.yaml) for more information. - This would prevent any unencrypted traffic from accidentally being transmitted from outside the Pod into the - Supervisor app's HTTP port. + Using either a Unix domain socket or a loopback interface listener would prevent any unencrypted traffic from + accidentally being transmitted from outside the Pod into the Supervisor app's HTTP port. For example, the following high level steps cover configuring Istio for use with the Supervisor: - - Update the http listener to use a Unix domain socket + - Update the HTTP listener to use a Unix domain socket i.e. `--data-value-yaml 'endpoints={"http":{"network":"unix","address":"/pinniped_socket/socketfile.sock"}}'` - Arrange for the Istio sidecar to be injected into the Supervisor app with an appropriate `IstioIngressListener` i.e `defaultEndpoint: unix:///pinniped_socket/socketfile.sock` - Mount the socket volume into the Istio sidecar container by including the appropriate annotation on the Supervisor pods i.e. `sidecar.istio.io/userVolumeMount: '{"socket":{"mountPath":"/pinniped_socket"}}'` - - Disable the https listener and update the deployment health checks as desired + - Disable the HTTPS listener and update the deployment health checks as desired - For service meshes that do not support Unix domain sockets, the http listener should be configured to listen on 127.0.0.1. + For service meshes that do not support Unix domain sockets, the HTTP listener should be configured as a TCP listener on a loopback interface. ## Creating a Service to expose the Supervisor app's endpoints within the cluster From bdabdf0f4225b706e2688c86ca318a2ce21903d6 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Tue, 5 Apr 2022 09:53:22 -0700 Subject: [PATCH 05/10] Update comment in FederationDomainTLSSpec --- .../config/v1alpha1/types_federationdomain.go.tmpl | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ generated/1.17/README.adoc | 2 +- .../config/v1alpha1/types_federationdomain.go | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ generated/1.18/README.adoc | 2 +- .../config/v1alpha1/types_federationdomain.go | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ generated/1.19/README.adoc | 2 +- .../config/v1alpha1/types_federationdomain.go | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ generated/1.20/README.adoc | 2 +- .../config/v1alpha1/types_federationdomain.go | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ generated/1.21/README.adoc | 2 +- .../config/v1alpha1/types_federationdomain.go | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ generated/1.22/README.adoc | 2 +- .../config/v1alpha1/types_federationdomain.go | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ generated/1.23/README.adoc | 2 +- .../config/v1alpha1/types_federationdomain.go | 5 +++-- ...g.supervisor.pinniped.dev_federationdomains.yaml | 13 +++++++------ .../config/v1alpha1/types_federationdomain.go | 5 +++-- 24 files changed, 90 insertions(+), 73 deletions(-) diff --git a/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl b/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl index e92303a9..27de4401 100644 --- a/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl +++ b/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml b/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/1.17/README.adoc b/generated/1.17/README.adoc index c9a9b07e..9efe8a67 100644 --- a/generated/1.17/README.adoc +++ b/generated/1.17/README.adoc @@ -538,7 +538,7 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an | *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. - SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. + SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. |=== diff --git a/generated/1.17/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.17/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/1.17/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.17/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/generated/1.17/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.17/crds/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/generated/1.17/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.17/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/1.18/README.adoc b/generated/1.18/README.adoc index fce0e2ba..f6ecc0f5 100644 --- a/generated/1.18/README.adoc +++ b/generated/1.18/README.adoc @@ -538,7 +538,7 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an | *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. - SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. + SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. |=== diff --git a/generated/1.18/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.18/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/1.18/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.18/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/generated/1.18/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.18/crds/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/generated/1.18/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.18/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/1.19/README.adoc b/generated/1.19/README.adoc index b2ac07a4..197ed326 100644 --- a/generated/1.19/README.adoc +++ b/generated/1.19/README.adoc @@ -538,7 +538,7 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an | *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. - SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. + SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. |=== diff --git a/generated/1.19/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.19/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/1.19/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.19/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/generated/1.19/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.19/crds/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/generated/1.19/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.19/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/1.20/README.adoc b/generated/1.20/README.adoc index 9bf80a58..8ad43876 100644 --- a/generated/1.20/README.adoc +++ b/generated/1.20/README.adoc @@ -538,7 +538,7 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an | *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. - SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. + SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. |=== diff --git a/generated/1.20/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.20/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/1.20/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.20/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/generated/1.20/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.20/crds/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/generated/1.20/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.20/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/1.21/README.adoc b/generated/1.21/README.adoc index d0c24b66..6abd6c4b 100644 --- a/generated/1.21/README.adoc +++ b/generated/1.21/README.adoc @@ -538,7 +538,7 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an | *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. - SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. + SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. |=== diff --git a/generated/1.21/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.21/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/1.21/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.21/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/generated/1.21/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.21/crds/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/generated/1.21/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.21/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/1.22/README.adoc b/generated/1.22/README.adoc index ae5b4564..46e9a2e5 100644 --- a/generated/1.22/README.adoc +++ b/generated/1.22/README.adoc @@ -538,7 +538,7 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an | *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. - SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. + SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. |=== diff --git a/generated/1.22/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.22/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/1.22/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.22/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/generated/1.22/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.22/crds/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/generated/1.22/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.22/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/1.23/README.adoc b/generated/1.23/README.adoc index b341bc4a..9d67cb25 100644 --- a/generated/1.23/README.adoc +++ b/generated/1.23/README.adoc @@ -538,7 +538,7 @@ FederationDomainTLSSpec is a struct that describes the TLS configuration for an | *`secretName`* __string__ | SecretName is an optional name of a Secret in the same namespace, of type `kubernetes.io/tls`, which contains the TLS serving certificate for the HTTPS endpoints served by this FederationDomain. When provided, the TLS Secret named here must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) supported by all major browsers. SecretName is required if you would like to use different TLS certificates for issuers of different hostnames. SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. - SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. + SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to use the default TLS certificate, which is configured elsewhere. When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. |=== diff --git a/generated/1.23/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.23/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/1.23/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.23/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. diff --git a/generated/1.23/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.23/crds/config.supervisor.pinniped.dev_federationdomains.yaml index c9f969a3..71f7370d 100644 --- a/generated/1.23/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.23/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -76,12 +76,13 @@ spec: so all issuers with the same DNS hostname must use the same SecretName value even if they have different port numbers. \n SecretName is not required when you would like to use only the - HTTP endpoints (e.g. when terminating TLS at an Ingress). It - is also not required when you would like all requests to this - OIDC Provider's HTTPS endpoints to use the default TLS certificate, - which is configured elsewhere. \n When your Issuer URL's host - is an IP address, then this field is ignored. SNI does not work - for IP addresses." + HTTP endpoints (e.g. when the HTTP listener is configured to + listen on loopback interfaces or UNIX domain sockets for traffic + from a service mesh sidecar). It is also not required when you + would like all requests to this OIDC Provider's HTTPS endpoints + to use the default TLS certificate, which is configured elsewhere. + \n When your Issuer URL's host is an IP address, then this field + is ignored. SNI does not work for IP addresses." type: string type: object required: diff --git a/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go index e92303a9..27de4401 100644 --- a/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -31,8 +31,9 @@ type FederationDomainTLSSpec struct { // SNI requests do not include port numbers, so all issuers with the same DNS hostname must use the same // SecretName value even if they have different port numbers. // - // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when terminating TLS at an - // Ingress). It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to + // SecretName is not required when you would like to use only the HTTP endpoints (e.g. when the HTTP listener is + // configured to listen on loopback interfaces or UNIX domain sockets for traffic from a service mesh sidecar). + // It is also not required when you would like all requests to this OIDC Provider's HTTPS endpoints to // use the default TLS certificate, which is configured elsewhere. // // When your Issuer URL's host is an IP address, then this field is ignored. SNI does not work for IP addresses. From 12cbd744b76581c750b69bba12341531c5634776 Mon Sep 17 00:00:00 2001 From: Mo Khan Date: Wed, 6 Apr 2022 15:31:07 -0400 Subject: [PATCH 06/10] Syntax highlighting for Dockerfile_fips --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index cfe81844..b5d19a16 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ *.go.tmpl linguist-language=Go +Dockerfile_fips linguist-language=Dockerfile generated/** linguist-generated From 3c6f97a457e6b9c492e0c17721640b9e1483e75c Mon Sep 17 00:00:00 2001 From: Mo Khan Date: Wed, 6 Apr 2022 15:32:08 -0400 Subject: [PATCH 07/10] Target hack/Dockerfile_fips correctly --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index b5d19a16..91efdea8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,3 @@ *.go.tmpl linguist-language=Go -Dockerfile_fips linguist-language=Dockerfile +hack/Dockerfile_fips linguist-language=Dockerfile generated/** linguist-generated From 91681b936878edf6415f33ece836d1f304f4c0f6 Mon Sep 17 00:00:00 2001 From: anjalitelang <49958114+anjaltelang@users.noreply.github.com> Date: Wed, 6 Apr 2022 16:08:04 -0400 Subject: [PATCH 08/10] Update ROADMAP.md Edits to the wiki based on our current backlog 4/5/2022 --- ROADMAP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 8f0e5f33..49420bb6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -37,9 +37,9 @@ Last Updated: March 2022 |Theme|Description|Timeline| |--|--|--| |Improving Security Posture|Support FIPS compliant Boring crypto libraries |March/April 2022| -|Improving Security Posture|TLS hardening |March/April 2022| |Improving Security Posture|Support Audit logging of security events related to Authentication |April/May 2022| |Improving Usability|Support for integrating with UI/Dashboards |June/July 2022| +|Improving Security Posture|TLS hardening contd|June/July 2022| |Multiple IDP support|Support multiple IDPs configured on a single Supervisor|Exploring/Ongoing| |Improving Security Posture|mTLS for Supervisor sessions |Exploring/Ongoing| |Improving Security Posture|Key management/rotation for Pinniped components with minimal downtime |Exploring/Ongoing| From 721526b7e758e5d469e051ab93ab8dd9388e187f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Apr 2022 14:13:12 +0000 Subject: [PATCH 09/10] Bump distroless/static from `80c956f` to `2556293` in /hack Bumps distroless/static from `80c956f` to `2556293`. --- updated-dependencies: - dependency-name: distroless/static dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- hack/Dockerfile_fips | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/Dockerfile_fips b/hack/Dockerfile_fips index 1dfbc243..800e58a2 100644 --- a/hack/Dockerfile_fips +++ b/hack/Dockerfile_fips @@ -54,7 +54,7 @@ RUN \ ln -s /usr/local/bin/pinniped-server /usr/local/bin/local-user-authenticator # Use a distroless runtime image with CA certificates, timezone data, and not much else. -FROM gcr.io/distroless/static:nonroot@sha256:80c956fb0836a17a565c43a4026c9c80b2013c83bea09f74fa4da195a59b7a99 +FROM gcr.io/distroless/static:nonroot@sha256:2556293984c5738fc75208cce52cf0a4762c709cf38e4bf8def65a61992da0ad # Copy the server binary from the build-env stage. COPY --from=build-env /usr/local/bin /usr/local/bin From 6b4fbb6e0e408a891c1da1302fb23848452eaa32 Mon Sep 17 00:00:00 2001 From: Monis Khan Date: Tue, 12 Apr 2022 14:27:07 -0400 Subject: [PATCH 10/10] Use klog to make sure FIPS init log is emitted We cannot use plog until the log level config has been setup, but that occurs after this init function has run. Signed-off-by: Monis Khan --- internal/crypto/ptls/fips_strict.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/crypto/ptls/fips_strict.go b/internal/crypto/ptls/fips_strict.go index a6a3c65d..a48a0dfe 100644 --- a/internal/crypto/ptls/fips_strict.go +++ b/internal/crypto/ptls/fips_strict.go @@ -18,8 +18,7 @@ import ( _ "crypto/tls/fipsonly" // restricts all TLS configuration to FIPS-approved settings. "k8s.io/apiserver/pkg/server/options" - - "go.pinniped.dev/internal/plog" + "k8s.io/klog/v2" ) // Always use TLS 1.2 for FIPs @@ -27,7 +26,11 @@ const secureServingOptionsMinTLSVersion = "VersionTLS12" const SecureTLSConfigMinTLSVersion = tls.VersionTLS12 func init() { - plog.Debug("using boring crypto in fips only mode", "go version", runtime.Version()) + // this init runs before we have parsed our config to determine our log level + // thus we must use a log statement that will always print instead of conditionally print + // for plog, that is only error and warning logs, neither of which seem appropriate here + // therefore, just use klog directly with no V level requirement + klog.InfoS("using boring crypto in fips only mode", "go version", runtime.Version()) } func Default(rootCAs *x509.CertPool) *tls.Config {