Add IPv6 test to WebhookAuthenticator ctrl tests

Co-authored-by: Benjamin A. Petersen <ben@benjaminapetersen.me>
This commit is contained in:
Joshua Casey
2024-03-19 12:31:11 -05:00
committed by Benjamin A. Petersen
parent 5c0d67dc50
commit 90e7343fb5

View File

@@ -117,7 +117,7 @@ func TestController(t *testing.T) {
})
localWithExampleDotComMux := http.NewServeMux()
localWithExampleDotComCertServer := tlsserver.TLSTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hostLocalWithExampleDotComCertServer := tlsserver.TLSTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tlsserver.AssertTLS(t, r, ptls.Default)
localWithExampleDotComMux.ServeHTTP(w, r)
}), func(thisServer *httptest.Server) {
@@ -129,7 +129,7 @@ func TestController(t *testing.T) {
})
goodMux := http.NewServeMux()
goodWebhookServer := tlsserver.TLSTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hostGoodDefaultServingCertServer := tlsserver.TLSTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tlsserver.AssertTLS(t, r, ptls.Default)
goodMux.ServeHTTP(w, r)
}), tlsserver.RecordTLSHello)
@@ -142,14 +142,17 @@ func TestController(t *testing.T) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprint(w, "404 nothing here")
}))
goodEndpoint := goodWebhookServer.URL
goodEndpointBut404 := goodEndpoint + "/nothing/here"
goodWebhookDefaultServingCertEndpoint := hostGoodDefaultServingCertServer.URL
goodWebhookDefaultServingCertEndpointBut404 := goodWebhookDefaultServingCertEndpoint + "/nothing/here"
localhostURL, err := url.Parse(hostAsLocalhostWebhookServer.URL)
require.NoError(t, err)
localhostEndpointURL := fmt.Sprintf("%s:%s", "https://localhost", localhostURL.Port())
badEndpoint := "https://.café .com/café/café/café/coffee"
hostAs127001WebhookServerURL, err := url.Parse(hostAs127001WebhookServer.URL)
require.NoError(t, err)
badEndpointInvalidURL := "https://.café .com/café/café/café/coffee"
badEndpointNoHTTPS := "http://localhost"
nowDoesntMatter := time.Date(1122, time.September, 33, 4, 55, 56, 778899, time.Local)
@@ -160,39 +163,32 @@ func TestController(t *testing.T) {
frozenTimeInThePast := metav1.NewTime(timeInThePast)
goodWebhookAuthenticatorSpecWithCA := auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: goodEndpoint,
TLS: conciergetestutil.TLSSpecFromTLSConfig(goodWebhookServer.TLS),
}
localhostWebhookAuthenticatorSpecWithCA := auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: localhostEndpointURL,
TLS: &auth1alpha1.TLSSpec{
// CA Bundle for validating the server's certs
CertificateAuthorityData: base64.StdEncoding.EncodeToString(caForLocalhostAsHostname.Bundle()),
},
Endpoint: goodWebhookDefaultServingCertEndpoint,
TLS: conciergetestutil.TLSSpecFromTLSConfig(hostGoodDefaultServingCertServer.TLS),
}
localWithExampleDotComWeebhookAuthenticatorSpec := auth1alpha1.WebhookAuthenticatorSpec{
// CA for example.com, TLS serving cert for example.com, but endpoint is still localhost
Endpoint: localWithExampleDotComCertServer.URL,
Endpoint: hostLocalWithExampleDotComCertServer.URL,
TLS: &auth1alpha1.TLSSpec{
// CA Bundle for example.com
CertificateAuthorityData: base64.StdEncoding.EncodeToString(caForExampleDotCom.Bundle()),
},
}
goodWebhookAuthenticatorSpecWithoutCA := auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: goodEndpoint,
Endpoint: goodWebhookDefaultServingCertEndpoint,
TLS: &auth1alpha1.TLSSpec{CertificateAuthorityData: ""},
}
goodWebhookAuthenticatorSpecWith404Endpoint := auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: goodEndpointBut404,
TLS: conciergetestutil.TLSSpecFromTLSConfig(goodWebhookServer.TLS),
Endpoint: goodWebhookDefaultServingCertEndpointBut404,
TLS: conciergetestutil.TLSSpecFromTLSConfig(hostGoodDefaultServingCertServer.TLS),
}
badWebhookAuthenticatorSpecInvalidTLS := auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: goodEndpoint,
Endpoint: goodWebhookDefaultServingCertEndpoint,
TLS: &auth1alpha1.TLSSpec{CertificateAuthorityData: "invalid base64-encoded data"},
}
badWebhookAuthenticatorSpecGoodEndpointButUnknownCA := auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: goodEndpoint,
Endpoint: goodWebhookDefaultServingCertEndpoint,
TLS: &auth1alpha1.TLSSpec{
CertificateAuthorityData: base64.StdEncoding.EncodeToString(pemServerCertForUnknownServer),
},
@@ -405,7 +401,7 @@ func TestController(t *testing.T) {
},
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
Phase: "Ready",
},
},
@@ -416,7 +412,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": goodWebhookServer.URL,
"endpoint": goodWebhookDefaultServingCertEndpoint,
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -440,7 +436,7 @@ func TestController(t *testing.T) {
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 666),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 666),
[]metav1.Condition{
sadReadyCondition(frozenTimeInThePast, 777),
happyEndpointURLValid(frozenTimeInThePast, 888),
@@ -456,7 +452,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": goodWebhookServer.URL,
"endpoint": goodWebhookDefaultServingCertEndpoint,
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -470,7 +466,7 @@ func TestController(t *testing.T) {
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
happyEndpointURLValid(frozenTimeInThePast, 0),
},
@@ -503,7 +499,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": goodWebhookServer.URL,
"endpoint": goodWebhookDefaultServingCertEndpoint,
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -516,7 +512,7 @@ func TestController(t *testing.T) {
},
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
Phase: "Ready",
},
})
@@ -548,7 +544,7 @@ func TestController(t *testing.T) {
Spec: goodWebhookAuthenticatorSpecWithoutCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
happyTLSConfigurationValidNoCA(frozenMetav1Now, 0),
sadTLSConnectionNegotiationValid(frozenMetav1Now, 0),
@@ -588,7 +584,7 @@ func TestController(t *testing.T) {
Spec: badWebhookAuthenticatorSpecInvalidTLS,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
sadTLSConfigurationValid(frozenMetav1Now, 0),
unknownTLSConnectionNegotiationValid(frozenMetav1Now, 0),
@@ -617,7 +613,7 @@ func TestController(t *testing.T) {
Name: "test-name",
},
Spec: auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: badEndpoint,
Endpoint: badEndpointInvalidURL,
},
},
},
@@ -627,11 +623,11 @@ func TestController(t *testing.T) {
Name: "test-name",
},
Spec: auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: badEndpoint,
Endpoint: badEndpointInvalidURL,
},
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
happyTLSConfigurationValidNoCA(frozenMetav1Now, 0),
sadEndpointURLValid("https://.café .com/café/café/café/coffee", frozenMetav1Now, 0),
@@ -674,7 +670,7 @@ func TestController(t *testing.T) {
},
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
happyTLSConfigurationValidNoCA(frozenMetav1Now, 0),
sadEndpointURLValidHTTPS("http://localhost", frozenMetav1Now, 0),
@@ -715,7 +711,7 @@ func TestController(t *testing.T) {
Spec: badWebhookAuthenticatorSpecGoodEndpointButUnknownCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
unknownAuthenticatorValid(frozenMetav1Now, 0),
sadReadyCondition(frozenMetav1Now, 0),
@@ -754,7 +750,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": goodEndpointBut404,
"endpoint": goodWebhookDefaultServingCertEndpointBut404,
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -767,7 +763,7 @@ func TestController(t *testing.T) {
},
Spec: goodWebhookAuthenticatorSpecWith404Endpoint,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(goodEndpointBut404, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpointBut404, frozenMetav1Now, 0),
Phase: "Ready",
},
})
@@ -780,16 +776,22 @@ func TestController(t *testing.T) {
},
wantCacheEntries: 1,
}, {
name: "validateTLSNegotiation: localhost hostname instead of 127.0.0.1 should still dial correctly as dialer should handle hostnames as well as IPv4 and IPv6 addresses",
name: "validateTLSNegotiation: localhost hostname instead of 127.0.0.1 should still dial correctly as dialer should handle hostnames as well as IPv4",
syncKey: controllerlib.Key{Name: "test-name"},
webhooks: []runtime.Object{
&auth1alpha1.WebhookAuthenticator{
ObjectMeta: metav1.ObjectMeta{
Name: "test-name",
},
Spec: localhostWebhookAuthenticatorSpecWithCA,
Spec: auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: fmt.Sprintf("%s:%s", "https://localhost", localhostURL.Port()),
TLS: &auth1alpha1.TLSSpec{
// CA Bundle for validating the server's certs
CertificateAuthorityData: base64.StdEncoding.EncodeToString(caForLocalhostAsHostname.Bundle()),
},
},
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(localhostEndpointURL, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(fmt.Sprintf("%s:%s", "https://localhost", localhostURL.Port()), frozenMetav1Now, 0),
Phase: "Ready",
},
},
@@ -800,7 +802,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": localhostEndpointURL,
"endpoint": fmt.Sprintf("%s:%s", "https://localhost", localhostURL.Port()),
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -813,6 +815,66 @@ func TestController(t *testing.T) {
}
},
wantCacheEntries: 1,
}, {
name: "validateTLSNegotiation: localhost IPv6 address instead of 127.0.0.1 should still dial correctly as dialer should handle addresses",
syncKey: controllerlib.Key{Name: "test-name"},
tlsDialerFunc: func(network string, addr string, config *tls.Config) (*tls.Conn, error) {
// We are dialing a different server here since CI doesn't have the linux IPv6 stack installed.
// This test proves that IPv6 addresses are parsed & handled correctly before we call tls.Dial in production code.
return tls.Dial(network, hostAs127001WebhookServerURL.Host, &tls.Config{
MinVersion: tls.VersionTLS12,
RootCAs: caForLocalhostAs127001.Pool(),
})
},
webhooks: []runtime.Object{
&auth1alpha1.WebhookAuthenticator{
ObjectMeta: metav1.ObjectMeta{
Name: "test-name",
},
Spec: auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: fmt.Sprintf("%s:%s", "https://[0:0:0:0:0:0:0:1]", hostAs127001WebhookServerURL.Port()),
TLS: &auth1alpha1.TLSSpec{
CertificateAuthorityData: base64.StdEncoding.EncodeToString(caForLocalhostAs127001.Bundle()),
},
},
},
},
wantLogs: []map[string]any{
{
"level": "info",
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": fmt.Sprintf("%s:%s", "https://[0:0:0:0:0:0:0:1]", hostAs127001WebhookServerURL.Port()),
"webhook": map[string]interface{}{
"name": "test-name",
},
},
},
wantActions: func() []coretesting.Action {
updateStatusAction := coretesting.NewUpdateAction(webhookAuthenticatorGVR, "", &auth1alpha1.WebhookAuthenticator{
ObjectMeta: metav1.ObjectMeta{
Name: "test-name",
},
Spec: auth1alpha1.WebhookAuthenticatorSpec{
Endpoint: fmt.Sprintf("%s:%s", "https://[0:0:0:0:0:0:0:1]", hostAs127001WebhookServerURL.Port()),
TLS: &auth1alpha1.TLSSpec{
CertificateAuthorityData: base64.StdEncoding.EncodeToString(caForLocalhostAs127001.Bundle()),
},
},
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(fmt.Sprintf("%s:%s", "https://[0:0:0:0:0:0:0:1]", hostAs127001WebhookServerURL.Port()), frozenMetav1Now, 0),
Phase: "Ready",
},
})
updateStatusAction.Subresource = "status"
return []coretesting.Action{
coretesting.NewListAction(webhookAuthenticatorGVR, webhookAuthenticatorGVK, "", metav1.ListOptions{}),
coretesting.NewWatchAction(webhookAuthenticatorGVR, "", metav1.ListOptions{}),
updateStatusAction,
}
},
wantCacheEntries: 1,
}, {
name: "validateTLSNegotiation: localhost as IP address 127.0.0.1 should still dial correctly as dialer should handle hostnames as well as IPv4 and IPv6 addresses",
syncKey: controllerlib.Key{Name: "test-name"},
@@ -862,7 +924,7 @@ func TestController(t *testing.T) {
},
Spec: localWithExampleDotComWeebhookAuthenticatorSpec,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(localWithExampleDotComCertServer.URL, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(hostLocalWithExampleDotComCertServer.URL, frozenMetav1Now, 0),
Phase: "Ready",
},
},
@@ -875,7 +937,7 @@ func TestController(t *testing.T) {
Spec: localWithExampleDotComWeebhookAuthenticatorSpec,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(localWithExampleDotComCertServer.URL, frozenMetav1Now, 0),
allHappyConditionsSuccess(hostLocalWithExampleDotComCertServer.URL, frozenMetav1Now, 0),
[]metav1.Condition{
sadTLSConnectionNegotiationNoIPSANs(frozenMetav1Now, 0),
unknownAuthenticatorValid(frozenMetav1Now, 0),
@@ -904,7 +966,7 @@ func TestController(t *testing.T) {
},
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
Phase: "Ready",
},
},
@@ -915,7 +977,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": goodWebhookServer.URL,
"endpoint": goodWebhookDefaultServingCertEndpoint,
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -939,7 +1001,7 @@ func TestController(t *testing.T) {
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
sadReadyCondition(frozenMetav1Now, 0),
},
@@ -954,7 +1016,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": goodWebhookServer.URL,
"endpoint": goodWebhookDefaultServingCertEndpoint,
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -967,7 +1029,7 @@ func TestController(t *testing.T) {
},
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
Phase: "Ready",
},
})
@@ -999,7 +1061,7 @@ func TestController(t *testing.T) {
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: conditionstestutil.Replace(
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
[]metav1.Condition{
sadReadyCondition(frozenMetav1Now, 0),
},
@@ -1014,7 +1076,7 @@ func TestController(t *testing.T) {
"timestamp": "2099-08-08T13:57:36.123456Z",
"logger": "webhookcachefiller-controller",
"message": "added new webhook authenticator",
"endpoint": goodWebhookServer.URL,
"endpoint": goodWebhookDefaultServingCertEndpoint,
"webhook": map[string]interface{}{
"name": "test-name",
},
@@ -1032,7 +1094,7 @@ func TestController(t *testing.T) {
},
Spec: goodWebhookAuthenticatorSpecWithCA,
Status: auth1alpha1.WebhookAuthenticatorStatus{
Conditions: allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
Conditions: allHappyConditionsSuccess(goodWebhookDefaultServingCertEndpoint, frozenMetav1Now, 0),
Phase: "Ready",
},
})