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
This commit is contained in:
Ryan Richard 2022-03-28 17:03:23 -07:00
parent 8d12c1b674
commit 488f08dd6e
10 changed files with 191 additions and 61 deletions

View File

@ -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 #! SPDX-License-Identifier: Apache-2.0
#@ load("@ytt:data", "data") #@ load("@ytt:data", "data")
@ -52,6 +52,7 @@ _: #@ template.replace(data.values.custom_labels)
#@ "defaultTLSCertificateSecret": defaultResourceNameWithSuffix("default-tls-certificate"), #@ "defaultTLSCertificateSecret": defaultResourceNameWithSuffix("default-tls-certificate"),
#@ }, #@ },
#@ "labels": labels(), #@ "labels": labels(),
#@ "insecure_accept_external_unencrypted_http_requests": data.values.deprecated_insecure_accept_external_unencrypted_http_requests
#@ } #@ }
#@ if data.values.log_level: #@ if data.values.log_level:
#@ config["logLevel"] = getAndValidateLogLevel() #@ config["logLevel"] = getAndValidateLogLevel()

View File

@ -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 #! SPDX-License-Identifier: Apache-2.0
#@ load("@ytt:data", "data") #@ load("@ytt:data", "data")
#@ load("helpers.lib.yaml", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix") #@ 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 apiVersion: v1
kind: Service kind: Service
@ -19,13 +32,13 @@ spec:
type: NodePort type: NodePort
selector: #@ deploymentPodLabel() selector: #@ deploymentPodLabel()
ports: ports:
#@ if data.values.service_http_nodeport_port: #@ if data.values.deprecated_service_http_nodeport_port:
- name: http - name: http
protocol: TCP protocol: TCP
port: #@ data.values.service_http_nodeport_port port: #@ data.values.deprecated_service_http_nodeport_port
targetPort: 8080 targetPort: 8080
#@ if data.values.service_http_nodeport_nodeport: #@ if data.values.deprecated_service_http_nodeport_nodeport:
nodePort: #@ data.values.service_http_nodeport_nodeport nodePort: #@ data.values.deprecated_service_http_nodeport_nodeport
#@ end #@ end
#@ end #@ end
#@ if data.values.service_https_nodeport_port: #@ if data.values.service_https_nodeport_port:
@ -39,7 +52,7 @@ spec:
#@ end #@ end
#@ 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 apiVersion: v1
kind: Service kind: Service
@ -54,10 +67,10 @@ spec:
type: ClusterIP type: ClusterIP
selector: #@ deploymentPodLabel() selector: #@ deploymentPodLabel()
ports: ports:
#@ if data.values.service_http_clusterip_port: #@ if data.values.deprecated_service_http_clusterip_port:
- name: http - name: http
protocol: TCP protocol: TCP
port: #@ data.values.service_http_clusterip_port port: #@ data.values.deprecated_service_http_clusterip_port
targetPort: 8080 targetPort: 8080
#@ end #@ end
#@ if data.values.service_https_clusterip_port: #@ if data.values.service_https_clusterip_port:
@ -68,7 +81,7 @@ spec:
#@ end #@ end
#@ 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 apiVersion: v1
kind: Service kind: Service
@ -86,10 +99,10 @@ spec:
loadBalancerIP: #@ data.values.service_loadbalancer_ip loadBalancerIP: #@ data.values.service_loadbalancer_ip
#@ end #@ end
ports: ports:
#@ if data.values.service_http_loadbalancer_port: #@ if data.values.deprecated_service_http_loadbalancer_port:
- name: http - name: http
protocol: TCP protocol: TCP
port: #@ data.values.service_http_loadbalancer_port port: #@ data.values.deprecated_service_http_loadbalancer_port
targetPort: 8080 targetPort: 8080
#@ end #@ end
#@ if data.values.service_https_loadbalancer_port: #@ if data.values.service_https_loadbalancer_port:

View File

@ -35,26 +35,31 @@ image_tag: latest
#! Optional. #! Optional.
image_pull_dockerconfigjson: #! e.g. {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}} 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. #! 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, for either HTTP or HTTPS depending on your needs. #! Typically, you would set a value for only one of the following service types.
#! 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. They are all optional.
#! Setting any of these values means that a Service of that type will be created.
#! Note that all port numbers should be numbers (not strings), i.e. use ytt's `--data-value-yaml` instead of `--data-value`. #! 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 #! Several of these values have been deprecated and will be removed in a future release. Their names have been changed to
service_http_nodeport_nodeport: #! the `nodePort` value of the NodePort Service, optional when `service_http_nodeport_port` is specified; e.g. 31234 #! mark them as deprecated and to make it obvious upon upgrade to anyone who was using them that they have been deprecated.
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_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_clusterip_port: #! when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443 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_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_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 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. #! 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. #! Optional.
service_loadbalancer_ip: #! e.g. 1.2.3.4 service_loadbalancer_ip: #! e.g. 1.2.3.4
#! Specify the verbosity of logging: info ("nice to know" information), debug (developer #! Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information),
#! information), trace (timing information), all (kitchen sink). #! 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. 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 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. #! Optional.
endpoints: 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

View File

@ -10,13 +10,6 @@ nodes:
containerPort: 31243 containerPort: 31243
hostPort: 12344 hostPort: 12344
listenAddress: 127.0.0.1 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 - protocol: TCP
# This same port number is hardcoded in the integration test setup # 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 # when creating a Service on a kind cluster. It is used to talk to

View File

@ -187,7 +187,7 @@ fi
log_note "Checking for running kind cluster..." log_note "Checking for running kind cluster..."
if ! kind get clusters | grep -q -e '^pinniped$'; then if ! kind get clusters | grep -q -e '^pinniped$'; then
log_note "Creating a kind cluster..." 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 ./hack/kind-up.sh
else else
if ! kubectl cluster-info | grep -E '(master|control plane)' | grep -q 127.0.0.1; then 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_namespace="supervisor"
supervisor_custom_labels="{mySupervisorCustomLabelName: mySupervisorCustomLabelValue}" supervisor_custom_labels="{mySupervisorCustomLabelName: mySupervisorCustomLabelValue}"
log_level="debug" log_level="debug"
service_http_nodeport_port="80"
service_http_nodeport_nodeport="31234"
service_https_nodeport_port="443" service_https_nodeport_port="443"
service_https_nodeport_nodeport="31243" service_https_nodeport_nodeport="31243"
service_https_clusterip_port="443" service_https_clusterip_port="443"
@ -311,15 +309,10 @@ else
--data-value "image_tag=$tag" \ --data-value "image_tag=$tag" \
--data-value "log_level=$log_level" \ --data-value "log_level=$log_level" \
--data-value-yaml "custom_labels=$supervisor_custom_labels" \ --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_port=$service_https_nodeport_port" \
--data-value-yaml "service_https_nodeport_nodeport=$service_https_nodeport_nodeport" \ --data-value-yaml "service_https_nodeport_nodeport=$service_https_nodeport_nodeport" \
--data-value-yaml "service_https_clusterip_port=$service_https_clusterip_port" \ --data-value-yaml "service_https_clusterip_port=$service_https_clusterip_port" \
>"$manifest" >"$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" kapp deploy --yes --app "$supervisor_app_name" --diff-changes --file "$manifest"
kubectl apply --dry-run=client -f "$manifest" # Validate manifest schema. 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_NAMESPACE=${supervisor_namespace}
export PINNIPED_TEST_SUPERVISOR_APP_NAME=${supervisor_app_name} export PINNIPED_TEST_SUPERVISOR_APP_NAME=${supervisor_app_name}
export PINNIPED_TEST_SUPERVISOR_CUSTOM_LABELS='${supervisor_custom_labels}' 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_SUPERVISOR_HTTPS_ADDRESS="localhost:12344"
export PINNIPED_TEST_PROXY=http://127.0.0.1:12346 export PINNIPED_TEST_PROXY=http://127.0.0.1:12346
export PINNIPED_TEST_LDAP_HOST=ldap.tools.svc.cluster.local export PINNIPED_TEST_LDAP_HOST=ldap.tools.svc.cluster.local

View File

@ -76,7 +76,7 @@ func FromPath(path string) (*Config, error) {
if err := validateEndpoint(*config.Endpoints.HTTP); err != nil { if err := validateEndpoint(*config.Endpoints.HTTP); err != nil {
return nil, fmt.Errorf("validate http endpoint: %w", err) 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) return nil, fmt.Errorf("validate http endpoint: %w", err)
} }
if err := validateAtLeastOneEnabledEndpoint(*config.Endpoints.HTTPS, *config.Endpoints.HTTP); err != nil { 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 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( return fmt.Errorf(
"http listener address %q for %q network may only bind to loopback interfaces", "http listener address %q for %q network may only bind to loopback interfaces",
endpoint.Address, 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. // Input was :port. This would bind to all interfaces, so it is not only on loopback.
return false return false
} }
if host == "localhost" { if host == "localhost" || host == "ip6-localhost" || host == "ip6-loopback" {
// This is only on 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 return true
} }
// The host could be a hostname, an IPv4 address, or an IPv6 address. // The host could be a hostname, an IPv4 address, or an IPv6 address.

View File

@ -39,6 +39,7 @@ func TestFromPath(t *testing.T) {
http: http:
network: tcp network: tcp
address: 127.0.0.1:1234 address: 127.0.0.1:1234
insecure_accept_external_unencrypted_http_requests: false
`), `),
wantConfig: &Config{ wantConfig: &Config{
APIGroupSuffix: pointer.StringPtr("some.suffix.com"), APIGroupSuffix: pointer.StringPtr("some.suffix.com"),
@ -59,6 +60,7 @@ func TestFromPath(t *testing.T) {
Address: "127.0.0.1:1234", Address: "127.0.0.1:1234",
}, },
}, },
AllowExternalHTTP: "false",
}, },
}, },
{ {
@ -83,6 +85,7 @@ func TestFromPath(t *testing.T) {
Network: "disabled", Network: "disabled",
}, },
}, },
AllowExternalHTTP: "",
}, },
}, },
{ {
@ -128,7 +131,7 @@ func TestFromPath(t *testing.T) {
wantError: `validate http endpoint: unknown network "bar"`, 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(` yaml: here.Doc(`
--- ---
names: 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`, 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", name: "endpoint disabled with non-empty address",
yaml: here.Doc(` yaml: here.Doc(`
@ -234,6 +331,14 @@ func TestAddrIsOnlyOnLoopback(t *testing.T) {
{addr: "localhost:0", want: true}, {addr: "localhost:0", want: true},
{addr: "localhost:80", want: true}, {addr: "localhost:80", want: true},
{addr: "localhost:http", 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:", want: true},
{addr: "127.0.0.1:0", want: true}, {addr: "127.0.0.1:0", want: true},
{addr: "127.0.0.1:80", want: true}, {addr: "127.0.0.1:80", want: true},

View File

@ -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 // SPDX-License-Identifier: Apache-2.0
package supervisor package supervisor
@ -7,11 +7,12 @@ import "go.pinniped.dev/internal/plog"
// Config contains knobs to setup an instance of the Pinniped Supervisor. // Config contains knobs to setup an instance of the Pinniped Supervisor.
type Config struct { type Config struct {
APIGroupSuffix *string `json:"apiGroupSuffix,omitempty"` APIGroupSuffix *string `json:"apiGroupSuffix,omitempty"`
Labels map[string]string `json:"labels"` Labels map[string]string `json:"labels"`
NamesConfig NamesConfigSpec `json:"names"` NamesConfig NamesConfigSpec `json:"names"`
LogLevel plog.LogLevel `json:"logLevel"` LogLevel plog.LogLevel `json:"logLevel"`
Endpoints *Endpoints `json:"endpoints"` Endpoints *Endpoints `json:"endpoints"`
AllowExternalHTTP string `json:"insecure_accept_external_unencrypted_http_requests"`
} }
// NamesConfigSpec configures the names of some Kubernetes resources for the Supervisor. // NamesConfigSpec configures the names of some Kubernetes resources for the Supervisor.

View File

@ -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. 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 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 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 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 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 Otherwise, the Kubernetes documentation provides a list of popular
[Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), including [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 [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/)). - Or, expose the Supervisor app using a Kubernetes service mesh technology (e.g. [Istio](https://istio.io/)).

View File

@ -48,7 +48,6 @@ type TestEnv struct {
KubernetesDistribution KubeDistro `json:"kubernetesDistribution"` KubernetesDistribution KubeDistro `json:"kubernetesDistribution"`
Capabilities map[Capability]bool `json:"capabilities"` Capabilities map[Capability]bool `json:"capabilities"`
TestWebhook auth1alpha1.WebhookAuthenticatorSpec `json:"testWebhook"` TestWebhook auth1alpha1.WebhookAuthenticatorSpec `json:"testWebhook"`
SupervisorHTTPAddress string `json:"supervisorHttpAddress"`
SupervisorHTTPSAddress string `json:"supervisorHttpsAddress"` SupervisorHTTPSAddress string `json:"supervisorHttpsAddress"`
SupervisorHTTPSIngressAddress string `json:"supervisorHttpsIngressAddress"` SupervisorHTTPSIngressAddress string `json:"supervisorHttpsIngressAddress"`
SupervisorHTTPSIngressCABundle string `json:"supervisorHttpsIngressCABundle"` 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.SupervisorAppName = needEnv(t, "PINNIPED_TEST_SUPERVISOR_APP_NAME")
result.TestWebhook.TLS = &auth1alpha1.TLSSpec{CertificateAuthorityData: needEnv(t, "PINNIPED_TEST_WEBHOOK_CA_BUNDLE")} result.TestWebhook.TLS = &auth1alpha1.TLSSpec{CertificateAuthorityData: needEnv(t, "PINNIPED_TEST_WEBHOOK_CA_BUNDLE")}
result.SupervisorHTTPAddress = os.Getenv("PINNIPED_TEST_SUPERVISOR_HTTP_ADDRESS") result.SupervisorHTTPSIngressAddress = needEnv(t, "PINNIPED_TEST_SUPERVISOR_HTTPS_INGRESS_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.SupervisorHTTPSAddress = needEnv(t, "PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS") result.SupervisorHTTPSAddress = needEnv(t, "PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS")
require.NotRegexp(t, "^[0-9]", result.SupervisorHTTPSAddress, 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", "PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS must be a hostname with an optional port and cannot be an IP address",