pay attention to web proxy settings during connection probes

- WebhookAuthenticator will now detect the proxy setting and skip
  dialing the connection probe if it should go through a proxy
- GitHubIdentityProvider will avoid using tls.Dial altogether
  by instead making a real request to the GitHub API as its
  connection probe, because this will respect the proxy settings
This commit is contained in:
Ryan Richard
2024-10-10 10:41:31 -07:00
parent 60cfa470b5
commit 4f661aaa69
13 changed files with 643 additions and 209 deletions
@@ -153,14 +153,16 @@ func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
t.Cleanup(cancel)
conciergeUsingHTTPSProxy := testlib.DeploymentsContainerHasHTTPSProxyEnvVar(t, env.ConciergeNamespace, env.ConciergeAppName)
caBundleSomePivotalCA := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURVVENDQWptZ0F3SUJBZ0lWQUpzNStTbVRtaTJXeUI0bGJJRXBXaUs5a1RkUE1BMEdDU3FHU0liM0RRRUIKQ3dVQU1COHhDekFKQmdOVkJBWVRBbFZUTVJBd0RnWURWUVFLREFkUWFYWnZkR0ZzTUI0WERUSXdNRFV3TkRFMgpNamMxT0ZvWERUSTBNRFV3TlRFMk1qYzFPRm93SHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFREFPQmdOVkJBb01CMUJwCmRtOTBZV3d3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRERZWmZvWGR4Z2NXTEMKZEJtbHB5a0tBaG9JMlBuUWtsVFNXMno1cGcwaXJjOGFRL1E3MXZzMTRZYStmdWtFTGlvOTRZYWw4R01DdVFrbApMZ3AvUEE5N1VYelhQNDBpK25iNXcwRGpwWWd2dU9KQXJXMno2MFRnWE5NSFh3VHk4ME1SZEhpUFVWZ0VZd0JpCmtkNThzdEFVS1Y1MnBQTU1reTJjNy9BcFhJNmRXR2xjalUvaFBsNmtpRzZ5dEw2REtGYjJQRWV3MmdJM3pHZ2IKOFVVbnA1V05DZDd2WjNVY0ZHNXlsZEd3aGc3cnZ4U1ZLWi9WOEhCMGJmbjlxamlrSVcxWFM4dzdpUUNlQmdQMApYZWhKZmVITlZJaTJtZlczNlVQbWpMdnVKaGpqNDIrdFBQWndvdDkzdWtlcEgvbWpHcFJEVm9wamJyWGlpTUYrCkYxdnlPNGMxQWdNQkFBR2pnWU13Z1lBd0hRWURWUjBPQkJZRUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1IKTUI4R0ExVWRJd1FZTUJhQUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1JNQjBHQTFVZEpRUVdNQlFHQ0NzRwpBUVVGQndNQ0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCCkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFYbEh4M2tIMDZwY2NDTDlEVE5qTnBCYnlVSytGd2R6T2IwWFYKcmpNaGtxdHVmdEpUUnR5T3hKZ0ZKNXhUR3pCdEtKamcrVU1pczBOV0t0VDBNWThVMU45U2c5SDl0RFpHRHBjVQpxMlVRU0Y4dXRQMVR3dnJIUzIrdzB2MUoxdHgrTEFiU0lmWmJCV0xXQ21EODUzRlVoWlFZekkvYXpFM28vd0p1CmlPUklMdUpNUk5vNlBXY3VLZmRFVkhaS1RTWnk3a25FcHNidGtsN3EwRE91eUFWdG9HVnlkb3VUR0FOdFhXK2YKczNUSTJjKzErZXg3L2RZOEJGQTFzNWFUOG5vZnU3T1RTTzdiS1kzSkRBUHZOeFQzKzVZUXJwNGR1Nmh0YUFMbAppOHNaRkhidmxpd2EzdlhxL3p1Y2JEaHEzQzBhZnAzV2ZwRGxwSlpvLy9QUUFKaTZLQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
tests := []struct {
name string
maybeSkip func(t *testing.T)
spec func() *authenticationv1alpha1.WebhookAuthenticatorSpec
initialPhase authenticationv1alpha1.WebhookAuthenticatorPhase
finalConditions []metav1.Condition
run func(t *testing.T)
}{
{
name: "basic test to see if the WebhookAuthenticator wakes up or not",
@@ -168,10 +170,15 @@ func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
return &env.TestWebhook
},
initialPhase: authenticationv1alpha1.WebhookAuthenticatorPhaseReady,
finalConditions: allSuccessfulWebhookAuthenticatorConditions(),
finalConditions: allSuccessfulWebhookAuthenticatorConditions(conciergeUsingHTTPSProxy),
},
{
name: "valid spec with invalid CA in TLS config will result in a WebhookAuthenticator that is not ready",
maybeSkip: func(t *testing.T) {
if conciergeUsingHTTPSProxy {
t.Skip("Skipping test that requires HTTPS_PROXY to be unset")
}
},
spec: func() *authenticationv1alpha1.WebhookAuthenticatorSpec {
caBundleString := "invalid base64-encoded data"
webhookSpec := env.TestWebhook.DeepCopy()
@@ -182,7 +189,7 @@ func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
},
initialPhase: authenticationv1alpha1.WebhookAuthenticatorPhaseError,
finalConditions: replaceSomeConditions(
allSuccessfulWebhookAuthenticatorConditions(),
allSuccessfulWebhookAuthenticatorConditions(false),
[]metav1.Condition{
{
Type: "Ready",
@@ -210,6 +217,11 @@ func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
},
{
name: "valid spec with valid CA in TLS config but does not match issuer server will result in a WebhookAuthenticator that is not ready",
maybeSkip: func(t *testing.T) {
if conciergeUsingHTTPSProxy {
t.Skip("Skipping test that requires HTTPS_PROXY to be unset")
}
},
spec: func() *authenticationv1alpha1.WebhookAuthenticatorSpec {
webhookSpec := env.TestWebhook.DeepCopy()
webhookSpec.TLS = &authenticationv1alpha1.TLSSpec{
@@ -219,7 +231,7 @@ func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
},
initialPhase: authenticationv1alpha1.WebhookAuthenticatorPhaseError,
finalConditions: replaceSomeConditions(
allSuccessfulWebhookAuthenticatorConditions(),
allSuccessfulWebhookAuthenticatorConditions(false),
[]metav1.Condition{
{
Type: "Ready",
@@ -242,6 +254,11 @@ func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
},
{
name: "invalid with unresponsive endpoint will result in a WebhookAuthenticator that is not ready",
maybeSkip: func(t *testing.T) {
if conciergeUsingHTTPSProxy {
t.Skip("Skipping test that requires HTTPS_PROXY to be unset")
}
},
spec: func() *authenticationv1alpha1.WebhookAuthenticatorSpec {
webhookSpec := env.TestWebhook.DeepCopy()
webhookSpec.TLS = &authenticationv1alpha1.TLSSpec{
@@ -252,7 +269,7 @@ func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
},
initialPhase: authenticationv1alpha1.WebhookAuthenticatorPhaseError,
finalConditions: replaceSomeConditions(
allSuccessfulWebhookAuthenticatorConditions(),
allSuccessfulWebhookAuthenticatorConditions(false),
[]metav1.Condition{
{
Type: "Ready",
@@ -397,7 +414,12 @@ func TestConciergeWebhookAuthenticatorCRDValidations_Parallel(t *testing.T) {
}
}
func allSuccessfulWebhookAuthenticatorConditions() []metav1.Condition {
func allSuccessfulWebhookAuthenticatorConditions(conciergeUsingHTTPSProxy bool) []metav1.Condition {
dialMessage := "successfully dialed webhook server"
if conciergeUsingHTTPSProxy {
dialMessage = "skipped dialing connection probe because HTTPS_PROXY is configured for use with the specified host"
}
return []metav1.Condition{
{
Type: "AuthenticatorValid",
@@ -427,7 +449,7 @@ func allSuccessfulWebhookAuthenticatorConditions() []metav1.Condition {
Type: "WebhookConnectionValid",
Status: "True",
Reason: "Success",
Message: "successfully dialed webhook server",
Message: dialMessage,
},
}
}
@@ -392,7 +392,7 @@ func TestGitHubIDPPhaseAndConditions_Parallel(t *testing.T) {
Type: "GitHubConnectionValid",
Status: metav1.ConditionTrue,
Reason: "Success",
Message: `dialed "api.github.com:443" for spec.githubAPI.host ("github.com"): host is reachable and TLS verification succeeds`,
Message: `probed connection to "api.github.com:443" for spec.githubAPI.host ("github.com"): host is reachable and TLS verification succeeds`,
},
{
Type: "HostValid",
@@ -461,7 +461,7 @@ func TestGitHubIDPPhaseAndConditions_Parallel(t *testing.T) {
Type: "GitHubConnectionValid",
Status: metav1.ConditionTrue,
Reason: "Success",
Message: `dialed "api.github.com:443" for spec.githubAPI.host ("api.github.com"): host is reachable and TLS verification succeeds`,
Message: `probed connection to "api.github.com:443" for spec.githubAPI.host ("api.github.com"): host is reachable and TLS verification succeeds`,
},
{
Type: "HostValid",
@@ -668,7 +668,7 @@ func TestGitHubIDPSecretInOtherNamespace_Parallel(t *testing.T) {
Type: "GitHubConnectionValid",
Status: metav1.ConditionTrue,
Reason: "Success",
Message: `dialed "api.github.com:443" for spec.githubAPI.host ("github.com"): host is reachable and TLS verification succeeds`,
Message: `probed connection to "api.github.com:443" for spec.githubAPI.host ("github.com"): host is reachable and TLS verification succeeds`,
},
{
Type: "HostValid",
+20
View File
@@ -1109,3 +1109,23 @@ func ObjectMetaWithRandomName(t *testing.T, baseName string) metav1.ObjectMeta {
Annotations: map[string]string{"pinniped.dev/testName": t.Name()},
}
}
func DeploymentsContainerHasHTTPSProxyEnvVar(t *testing.T, namespaceName string, deploymentName string) bool {
client := NewKubernetesClientset(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
d, err := client.AppsV1().Deployments(namespaceName).Get(ctx, deploymentName, metav1.GetOptions{})
require.NoError(t, err)
for _, c := range d.Spec.Template.Spec.Containers {
for _, e := range c.Env {
if e.Name == "HTTPS_PROXY" {
return true
}
}
}
return false
}