Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] support default-tls-secret #648

Closed
6 changes: 6 additions & 0 deletions config/config-gateway.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ data:
class: istio
gateway: istio-system/knative-local-gateway
service: istio-system/knative-local-gateway

# If auto-TLS is disabled fallback to the following certificate
#
# An operator is required to setup a ReferenceGrant
# for this secret to be used
default-tls-secret: "some-namespace/some-secret"
48 changes: 28 additions & 20 deletions pkg/reconciler/ingress/config/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/cache"
"knative.dev/pkg/configmap"
"sigs.k8s.io/yaml"

"knative.dev/networking/pkg/apis/networking/v1alpha1"
Expand All @@ -35,6 +36,8 @@ const (

visibilityConfigKey = "visibility"

defaultTLSSecretKey = "default-tls-secret" // #nosec G101

// defaultGatewayClass is the gatewayclass name for the gateway.
defaultGatewayClass = "istio"
)
Expand Down Expand Up @@ -73,35 +76,39 @@ type Gateway struct {
// corresponding gateway. If multiple selectors match, we choose
// the most specific selector.
Gateways map[v1alpha1.IngressVisibility]GatewayConfig

DefaultTLSSecret *types.NamespacedName
}

// NewGatewayFromConfigMap creates a Gateway from the supplied ConfigMap
func NewGatewayFromConfigMap(configMap *corev1.ConfigMap) (*Gateway, error) {
v, ok := configMap.Data[visibilityConfigKey]
if !ok {
// These are the defaults.
return &Gateway{
Gateways: map[v1alpha1.IngressVisibility]GatewayConfig{
v1alpha1.IngressVisibilityExternalIP: {GatewayClass: defaultGatewayClass, Gateway: defaultIstioGateway, Service: defaultGatewayService},
v1alpha1.IngressVisibilityClusterLocal: {GatewayClass: defaultGatewayClass, Gateway: defaultIstioLocalGateway, Service: defaultLocalGatewayService},
},
}, nil
}

visConfig := make(map[v1alpha1.IngressVisibility]visibilityValue)
if err := yaml.Unmarshal([]byte(v), &visConfig); err != nil {
var defaultTLSSecret *types.NamespacedName
if err := configmap.Parse(configMap.Data, configmap.AsOptionalNamespacedName(defaultTLSSecretKey, &defaultTLSSecret)); err != nil {
return nil, err
}

for _, vis := range []v1alpha1.IngressVisibility{
v1alpha1.IngressVisibilityClusterLocal,
v1alpha1.IngressVisibilityExternalIP,
} {
if _, ok := visConfig[vis]; !ok {
return nil, fmt.Errorf("visibility %q must not be empty", vis)
v, ok := configMap.Data[visibilityConfigKey]
visConfig := make(map[v1alpha1.IngressVisibility]visibilityValue)
if !ok {
// These are the defaults.
visConfig[v1alpha1.IngressVisibilityExternalIP] = visibilityValue{GatewayClass: defaultGatewayClass, Gateway: defaultIstioGateway.String(), Service: defaultGatewayService.String()}
visConfig[v1alpha1.IngressVisibilityClusterLocal] = visibilityValue{GatewayClass: defaultGatewayClass, Gateway: defaultIstioLocalGateway.String(), Service: defaultLocalGatewayService.String()}
} else {
if err := yaml.Unmarshal([]byte(v), &visConfig); err != nil {
return nil, err
}

for _, vis := range []v1alpha1.IngressVisibility{
v1alpha1.IngressVisibilityClusterLocal,
v1alpha1.IngressVisibilityExternalIP,
} {
if _, ok := visConfig[vis]; !ok {
return nil, fmt.Errorf("visibility %q must not be empty", vis)
}
}
}

}
entry := make(map[v1alpha1.IngressVisibility]GatewayConfig)
for key, value := range visConfig {
// Check that the visibility makes sense.
Expand All @@ -127,7 +134,8 @@ func NewGatewayFromConfigMap(configMap *corev1.ConfigMap) (*Gateway, error) {
Service: service,
}
}
return &Gateway{Gateways: entry}, nil

return &Gateway{Gateways: entry, DefaultTLSSecret: defaultTLSSecret}, nil
}

func parseNamespacedName(namespacedName string) (*types.NamespacedName, error) {
Expand Down
39 changes: 38 additions & 1 deletion pkg/reconciler/ingress/config/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,56 @@ limitations under the License.
package config

import (
"strings"
"testing"

. "knative.dev/pkg/configmap/testing"
)

var badVisibilityEntry = `
this isn't yaml???
`

var emptyVisibilityEntry = `

`

func TestGateway(t *testing.T) {
cm, example := ConfigMapsFromTestFile(t, GatewayConfigName)
cm, example := ConfigMapsFromTestFile(t, GatewayConfigName, defaultTLSSecretKey)

if _, err := NewGatewayFromConfigMap(cm); err != nil {
t.Error("NewContourFromConfigMap(actual) =", err)
}

cm.Data[defaultTLSSecretKey] = "secret-no-namespace"
if _, err := NewGatewayFromConfigMap(cm); err == nil {
t.Error("NewContourFromConfigMap(actual) with bad defaultTLSSecretKey value did not fail")
}

delete(cm.Data, defaultTLSSecretKey)

cm.Data[visibilityConfigKey] = badVisibilityEntry

_, err := NewGatewayFromConfigMap(cm)
expectedError := "error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type map[v1alpha1.IngressVisibility]config.visibilityValu"
if err == nil {
t.Error("NewContourFromConfigMap(actual) with bad visibility config value did not fail")
} else if !strings.Contains(err.Error(), expectedError) {
t.Error("NewContourFromConfigMap(actual) with bad visibility config failed with unexpected error message:", err)
}

cm.Data[visibilityConfigKey] = emptyVisibilityEntry

_, err = NewGatewayFromConfigMap(cm)
expectedError = "visibility \"ClusterLocal\" must not be empty"
if err == nil {
t.Error("NewContourFromConfigMap(actual) with empty visibility config value did not fail")
} else if !strings.Contains(err.Error(), expectedError) {
t.Error("NewContourFromConfigMap(actual) with empty visibility config value failed with unexpected error message:", err)
}

if _, err := NewGatewayFromConfigMap(example); err != nil {
t.Error("NewContourFromConfigMap(example) =", err)
}

}
7 changes: 7 additions & 0 deletions pkg/reconciler/ingress/config/testdata/config-gateway.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ metadata:
name: config-gateway
namespace: knative-serving
data:
default-tls-secret: test-ns/test-secret
_example: |
################################
# #
Expand Down Expand Up @@ -46,3 +47,9 @@ data:
class: istio
gateway: istio-system/knative-local-gateway
service: istio-system/knative-local-gateway

# If auto-TLS is disabled fallback to the following certificate
#
# An operator is required to setup a ReferenceGrant
# for this secret to be used
default-tls-secret: "some-namespace/some-secret"
5 changes: 5 additions & 0 deletions pkg/reconciler/ingress/config/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions pkg/reconciler/ingress/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,20 @@
listeners = append(listeners, l...)
}

if len(listeners) == 0 && gatewayConfig.DefaultTLSSecret != nil {
//AutoTLS is not on, but there is a defaultTLSSecret
ingressTLS := &v1alpha1.IngressTLS{
Hosts: getExternalVisibilityHostnames(ing),
SecretName: gatewayConfig.DefaultTLSSecret.Name,
SecretNamespace: gatewayConfig.DefaultTLSSecret.Namespace,
}
l, err := c.reconcileTLS(ctx, ingressTLS, ing)
if err != nil {
return err
}

Check warning on line 134 in pkg/reconciler/ingress/ingress.go

View check run for this annotation

Codecov / codecov/patch

pkg/reconciler/ingress/ingress.go#L133-L134

Added lines #L133 - L134 were not covered by tests
listeners = append(listeners, l...)
}

if len(listeners) > 0 {
// For now, we only reconcile the external visibility, because there's
// no way to provide TLS for internal listeners.
Expand Down Expand Up @@ -180,3 +194,18 @@
}
return false
}

func getExternalVisibilityHostnames(ing *v1alpha1.Ingress) []string {
var hostnames []string

for _, rule := range ing.Spec.Rules {
if rule.Visibility == v1alpha1.IngressVisibilityExternalIP {
if rule.Hosts != nil && len(rule.Hosts) > 0 {
hostnames = append(hostnames, rule.Hosts...)
}
}
}

return hostnames

}
Loading
Loading