Skip to content

Commit 31c90b2

Browse files
amend tchap suggestions
the change includes tests moving to `WaitForOperatorToPickUpChanges()` when authentication CR is updated, VerifyOAuthServerDeploymentProxyConfig() being used in now merged env var tests, ensuring no connect entries for squid proxy in relevant tests, and CA file reconfigure for squid proxy to verify hot reload behavior.
1 parent 0eefcb2 commit 31c90b2

1 file changed

Lines changed: 91 additions & 87 deletions

File tree

test/e2e-component-proxy/component_proxy_oidc_login.go

Lines changed: 91 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package component_proxy
22

33
import (
44
"context"
5+
"crypto/x509"
6+
"encoding/pem"
57
"fmt"
68
"io"
79
"net/url"
8-
"os"
9-
"path"
10+
"os/exec"
1011
"testing"
1112
"time"
1213

@@ -23,19 +24,15 @@ import (
2324

2425
"github.com/openshift/api/features"
2526
operatorv1 "github.com/openshift/api/operator/v1"
26-
"github.com/openshift/library-go/pkg/crypto"
2727
"github.com/openshift/library-go/pkg/oauth/tokenrequest"
2828
"github.com/openshift/library-go/pkg/oauth/tokenrequest/challengehandlers"
2929

3030
test "github.com/openshift/cluster-authentication-operator/test/library"
3131
)
3232

3333
var _ = g.Describe("[sig-auth] authentication operator", func() {
34-
g.It("[Serial][Operator][ComponentProxy] should set only HTTPS_PROXY env var when only httpsProxy is configured", func() {
35-
testPartialProxyEnvVars()
36-
})
37-
g.It("[Serial][Operator][ComponentProxy] should set both HTTP_PROXY and HTTPS_PROXY env vars when fully configured", func() {
38-
testFullProxyEnvVars()
34+
g.It("[Serial][Operator][ComponentProxy] should set partial and full env vars when configured", func() {
35+
testPartialFullProxyEnvVars()
3936
})
4037
g.It("[Serial][Operator][ComponentProxy] should apply proxy config and perform full OIDC login flow", func() {
4138
testProxyOIDCLoginFlow()
@@ -114,7 +111,7 @@ func assertOIDCLogin(t testing.TB, kubeConfig *rest.Config, routeClient test.Tes
114111
o.Expect(err).NotTo(o.HaveOccurred(), "OIDC login flow should succeed")
115112
}
116113

117-
func testPartialProxyEnvVars() {
114+
func testPartialFullProxyEnvVars() {
118115
ctx := context.Background()
119116
t := g.GinkgoTB()
120117
clients := test.NewTestClients(t)
@@ -126,7 +123,7 @@ func testPartialProxyEnvVars() {
126123
o.Expect(err).NotTo(o.HaveOccurred())
127124

128125
g.By("Deploying Squid forward proxy")
129-
proxyURL, _, _, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
126+
httpProxyURL, httpsProxyURL, caPEM, _, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
130127
g.DeferCleanup(func() {
131128
g.GinkgoWriter.Println("cleaning up: removing Squid proxy")
132129
proxyCleanup()
@@ -138,66 +135,59 @@ func testPartialProxyEnvVars() {
138135

139136
g.By("Setting only httpsProxy in component proxy config")
140137
operatorAuth.Spec.Proxy = operatorv1.AuthenticationProxyConfig{
141-
HTTPSProxy: proxyURL,
138+
HTTPSProxy: httpsProxyURL,
142139
}
143140
_, err = clients.OperatorClient.OperatorV1().Authentications().Update(ctx, operatorAuth, metav1.UpdateOptions{})
144141
o.Expect(err).NotTo(o.HaveOccurred())
145142

146143
g.By("Waiting for operator to reconcile proxy config")
147-
err = test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
144+
err = test.WaitForOperatorToPickUpChanges(t, clients.ConfigClient.ConfigV1(), "authentication")
148145
o.Expect(err).NotTo(o.HaveOccurred())
149146

150147
g.By("Verifying oauth-server has HTTPS_PROXY but not HTTP_PROXY")
151-
envVars := test.GetOAuthServerProxyEnvVars(t, clients.KubeClient)
152-
o.Expect(envVars).To(o.HaveKeyWithValue("HTTPS_PROXY", proxyURL))
153-
o.Expect(envVars).NotTo(o.HaveKey("HTTP_PROXY"))
154-
// NO_PROXY default values (.cluster.local, .svc, etc.) are verified in proxy_test.go unit tests
155-
o.Expect(envVars).To(o.HaveKey("NO_PROXY"))
156-
}
157-
158-
func testFullProxyEnvVars() {
159-
ctx := context.Background()
160-
t := g.GinkgoTB()
161-
clients := test.NewTestClients(t)
162-
163-
test.CheckFeatureGateEnabledOrSkip(t, clients.ConfigClient, features.FeatureGateAuthenticationComponentProxy)
148+
test.VerifyOAuthServerDeploymentProxyConfig(t, clients.KubeClient, "", httpsProxyURL, "", false)
164149

165-
g.By("Waiting for authentication operator to be stable before test")
166-
err := test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
167-
o.Expect(err).NotTo(o.HaveOccurred())
168-
169-
g.By("Deploying Squid forward proxy")
170-
proxyURL, _, _, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
150+
configMapName := "e2e-proxy-trusted-ca"
151+
caConfigMap := &corev1.ConfigMap{
152+
ObjectMeta: metav1.ObjectMeta{
153+
Name: configMapName,
154+
Namespace: "openshift-config",
155+
},
156+
Data: map[string]string{
157+
"ca-bundle.crt": string(caPEM),
158+
},
159+
}
160+
_, err = clients.KubeClient.CoreV1().ConfigMaps("openshift-config").Create(ctx, caConfigMap, metav1.CreateOptions{})
161+
o.Expect(err).NotTo(o.HaveOccurred(), "should be able to create trustedCA ConfigMap")
171162
g.DeferCleanup(func() {
172-
g.GinkgoWriter.Println("cleaning up: removing Squid proxy")
173-
proxyCleanup()
163+
if err := clients.KubeClient.CoreV1().ConfigMaps("openshift-config").Delete(ctx, configMapName, metav1.DeleteOptions{}); err != nil {
164+
g.GinkgoWriter.Printf("failed to clean up ConfigMap %s: %v\n", configMapName, err)
165+
}
174166
})
175167

176-
g.By("Saving original proxy config")
177-
operatorAuth, proxyConfigCleanup := test.SaveAndRestoreProxyConfig(t, clients.OperatorClient, clients.ConfigClient)
178-
g.DeferCleanup(proxyConfigCleanup)
179-
180168
noProxyHost := "noproxy.example.com"
181169

182-
g.By("Setting httpProxy, httpsProxy, and noProxy in component proxy config")
170+
operatorAuth, err = clients.OperatorClient.OperatorV1().Authentications().Get(ctx, "cluster", metav1.GetOptions{})
171+
o.Expect(err).NotTo(o.HaveOccurred())
172+
173+
g.By("Setting httpProxy, httpsProxy, noProxy, and trustedCA in component proxy config")
183174
operatorAuth.Spec.Proxy = operatorv1.AuthenticationProxyConfig{
184-
HTTPProxy: proxyURL,
185-
HTTPSProxy: proxyURL,
175+
HTTPProxy: httpProxyURL,
176+
HTTPSProxy: httpsProxyURL,
186177
NoProxy: []string{noProxyHost},
178+
TrustedCA: operatorv1.AuthenticationConfigMapReference{
179+
Name: configMapName,
180+
},
187181
}
188182
_, err = clients.OperatorClient.OperatorV1().Authentications().Update(ctx, operatorAuth, metav1.UpdateOptions{})
189183
o.Expect(err).NotTo(o.HaveOccurred())
190184

191185
g.By("Waiting for operator to reconcile proxy config")
192-
err = test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
186+
err = test.WaitForOperatorToPickUpChanges(t, clients.ConfigClient.ConfigV1(), "authentication")
193187
o.Expect(err).NotTo(o.HaveOccurred())
194188

195189
g.By("Verifying oauth-server has HTTP_PROXY, HTTPS_PROXY, and NO_PROXY with custom entry")
196-
envVars := test.GetOAuthServerProxyEnvVars(t, clients.KubeClient)
197-
o.Expect(envVars).To(o.HaveKeyWithValue("HTTP_PROXY", proxyURL))
198-
o.Expect(envVars).To(o.HaveKeyWithValue("HTTPS_PROXY", proxyURL))
199-
o.Expect(envVars).To(o.HaveKey("NO_PROXY"))
200-
o.Expect(envVars["NO_PROXY"]).To(o.ContainSubstring(noProxyHost))
190+
test.VerifyOAuthServerDeploymentProxyConfig(t, clients.KubeClient, httpProxyURL, httpsProxyURL, noProxyHost, true)
201191
}
202192

203193
func testProxyOIDCLoginFlow() {
@@ -213,7 +203,7 @@ func testProxyOIDCLoginFlow() {
213203
o.Expect(err).NotTo(o.HaveOccurred())
214204

215205
g.By("Deploying Squid forward proxy")
216-
proxyURL, _, proxyNamespace, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
206+
_, httpsProxyURL, _, proxyNamespace, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
217207
g.DeferCleanup(func() {
218208
g.GinkgoWriter.Println("cleaning up: removing Squid proxy")
219209
proxyCleanup()
@@ -224,7 +214,7 @@ func testProxyOIDCLoginFlow() {
224214
g.DeferCleanup(proxyConfigCleanup)
225215

226216
operatorAuth.Spec.Proxy = operatorv1.AuthenticationProxyConfig{
227-
HTTPSProxy: proxyURL,
217+
HTTPSProxy: httpsProxyURL,
228218
}
229219
_, err = clients.OperatorClient.OperatorV1().Authentications().Update(ctx, operatorAuth, metav1.UpdateOptions{})
230220
o.Expect(err).NotTo(o.HaveOccurred())
@@ -255,7 +245,7 @@ func testProxyOIDCLoginFlow() {
255245
})
256246

257247
g.By("Waiting for operator to reconcile proxy config")
258-
err = test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
248+
err = test.WaitForOperatorToPickUpChanges(t, clients.ConfigClient.ConfigV1(), "authentication")
259249
o.Expect(err).NotTo(o.HaveOccurred())
260250

261251
g.By("Creating Keycloak test user and group")
@@ -287,7 +277,7 @@ func testDirectIdPFallback() {
287277
o.Expect(err).NotTo(o.HaveOccurred())
288278

289279
g.By("Deploying Squid forward proxy")
290-
proxyURL, _, _, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
280+
_, httpsProxyURL, _, proxyNS, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
291281
g.DeferCleanup(func() {
292282
g.GinkgoWriter.Println("cleaning up: removing Squid proxy")
293283
proxyCleanup()
@@ -299,13 +289,13 @@ func testDirectIdPFallback() {
299289

300290
g.By("Setting component-scoped proxy config")
301291
operatorAuth.Spec.Proxy = operatorv1.AuthenticationProxyConfig{
302-
HTTPSProxy: proxyURL,
292+
HTTPSProxy: httpsProxyURL,
303293
}
304294
_, err = clients.OperatorClient.OperatorV1().Authentications().Update(ctx, operatorAuth, metav1.UpdateOptions{})
305295
o.Expect(err).NotTo(o.HaveOccurred())
306296

307297
g.By("Waiting for operator to reconcile proxy config")
308-
err = test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
298+
err = test.WaitForOperatorToPickUpChanges(t, clients.ConfigClient.ConfigV1(), "authentication")
309299
o.Expect(err).NotTo(o.HaveOccurred())
310300

311301
g.By("Deploying Keycloak and adding OIDC IdP")
@@ -317,6 +307,9 @@ func testDirectIdPFallback() {
317307
}
318308
}))
319309

310+
issuerURL, err := url.Parse(kcClient.IssuerURL())
311+
o.Expect(err).NotTo(o.HaveOccurred())
312+
320313
g.By("Creating Keycloak test user and group")
321314
group := "ocp-test-direct-fallback-group"
322315
o.Expect(kcClient.CreateGroup(group)).To(o.Succeed())
@@ -333,11 +326,16 @@ func testDirectIdPFallback() {
333326
o.Expect(err).NotTo(o.HaveOccurred())
334327

335328
g.By("Waiting for operator to reconcile proxy removal")
336-
err = test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
329+
err = test.WaitForOperatorToPickUpChanges(t, clients.ConfigClient.ConfigV1(), "authentication")
337330
o.Expect(err).NotTo(o.HaveOccurred())
338331

339332
g.By("Performing OIDC login flow via direct IdP connectivity after proxy removal")
340333
assertOIDCLogin(t, kubeConfig, *clients, username, password, group)
334+
335+
logs := test.GetSquidProxyLogs(t, clients.KubeClient, proxyNS)
336+
337+
keycloakHost := issuerURL.Hostname()
338+
o.Expect(logs).NotTo(o.ContainSubstring(keycloakHost), "squid logs should not contain keycloak connect")
341339
}
342340

343341
func testTrustedCAHotReload() {
@@ -353,7 +351,7 @@ func testTrustedCAHotReload() {
353351
o.Expect(err).NotTo(o.HaveOccurred())
354352

355353
g.By("Deploying Squid forward proxy")
356-
proxyURL, _, proxyNamespace, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
354+
_, httpsProxyURL, caFile, proxyNamespace, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
357355
g.DeferCleanup(func() {
358356
g.GinkgoWriter.Println("cleaning up: removing Squid proxy")
359357
proxyCleanup()
@@ -387,31 +385,14 @@ func testTrustedCAHotReload() {
387385
networkPolicyCleanup()
388386
})
389387

390-
g.By("Generating self-signed CA and creating trustedCA ConfigMap")
391-
tempDir, err := os.MkdirTemp("", "testca")
392-
o.Expect(err).NotTo(o.HaveOccurred())
393-
defer os.RemoveAll(tempDir)
394-
395-
ca, err := crypto.MakeSelfSignedCA(
396-
path.Join(tempDir, "ca.crt"),
397-
path.Join(tempDir, "ca.key"),
398-
path.Join(tempDir, "serial"),
399-
"proxy-e2e-ca",
400-
100*24*time.Hour,
401-
)
402-
o.Expect(err).NotTo(o.HaveOccurred())
403-
404-
caPEM, _, err := ca.Config.GetPEMBytes()
405-
o.Expect(err).NotTo(o.HaveOccurred())
406-
407388
configMapName := "e2e-proxy-trusted-ca"
408389
caConfigMap := &corev1.ConfigMap{
409390
ObjectMeta: metav1.ObjectMeta{
410391
Name: configMapName,
411392
Namespace: "openshift-config",
412393
},
413394
Data: map[string]string{
414-
"ca-bundle.crt": string(caPEM),
395+
"ca-bundle.crt": string(caFile),
415396
},
416397
}
417398
_, err = clients.KubeClient.CoreV1().ConfigMaps("openshift-config").Create(ctx, caConfigMap, metav1.CreateOptions{})
@@ -424,7 +405,7 @@ func testTrustedCAHotReload() {
424405

425406
g.By("Setting component-scoped proxy with trustedCA")
426407
operatorAuth.Spec.Proxy = operatorv1.AuthenticationProxyConfig{
427-
HTTPSProxy: proxyURL,
408+
HTTPSProxy: httpsProxyURL,
428409
TrustedCA: operatorv1.AuthenticationConfigMapReference{
429410
Name: configMapName,
430411
},
@@ -433,7 +414,7 @@ func testTrustedCAHotReload() {
433414
o.Expect(err).NotTo(o.HaveOccurred())
434415

435416
g.By("Waiting for operator to reconcile proxy config with trustedCA")
436-
err = test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
417+
err = test.WaitForOperatorToPickUpChanges(t, clients.ConfigClient.ConfigV1(), "authentication")
437418
o.Expect(err).NotTo(o.HaveOccurred())
438419

439420
g.By("Creating Keycloak test user and group")
@@ -464,22 +445,45 @@ func testTrustedCAHotReload() {
464445
podNamesBefore.Insert(pod.Name)
465446
}
466447

467-
g.By("Rotating CA: generating new self-signed CA and updating ConfigMap")
468-
newCA, err := crypto.MakeSelfSignedCA(
469-
path.Join(tempDir, "ca-new.crt"),
470-
path.Join(tempDir, "ca-new.key"),
471-
path.Join(tempDir, "serial-new"),
472-
"proxy-e2e-ca-rotated",
473-
100*24*time.Hour,
474-
)
448+
g.By("Rotating CA: generating new CA and server cert")
449+
newCA := test.NewCertificateAuthorityCertificate(t, nil)
450+
serviceDNS := fmt.Sprintf("squid-proxy.%s.svc.cluster.local", proxyNamespace)
451+
newServerCert := test.NewServerCertificate(t, newCA, serviceDNS)
452+
453+
newCACertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: newCA.Certificate.Raw})
454+
newServerCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: newServerCert.Certificate.Raw})
455+
newServerKeyDER, err := x509.MarshalPKCS8PrivateKey(newServerCert.PrivateKey)
456+
o.Expect(err).NotTo(o.HaveOccurred())
457+
newServerKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: newServerKeyDER})
458+
459+
g.By("Updating squid-tls Secret with rotated cert")
460+
tlsSecret, err := clients.KubeClient.CoreV1().Secrets(proxyNamespace).Get(ctx, "squid-tls", metav1.GetOptions{})
461+
o.Expect(err).NotTo(o.HaveOccurred())
462+
tlsSecret.Data["tls.crt"] = newServerCertPEM
463+
tlsSecret.Data["tls.key"] = newServerKeyPEM
464+
_, err = clients.KubeClient.CoreV1().Secrets(proxyNamespace).Update(ctx, tlsSecret, metav1.UpdateOptions{})
475465
o.Expect(err).NotTo(o.HaveOccurred())
476466

477-
newCAPEM, _, err := newCA.Config.GetPEMBytes()
467+
g.By("Reconfiguring Squid to pick up new cert")
468+
squidPods, err := clients.KubeClient.CoreV1().Pods(proxyNamespace).List(ctx, metav1.ListOptions{
469+
LabelSelector: "app=squid-proxy",
470+
})
478471
o.Expect(err).NotTo(o.HaveOccurred())
472+
o.Expect(squidPods.Items).NotTo(o.BeEmpty())
473+
474+
reconfigureCmd := exec.Command("oc", "exec",
475+
"-n", proxyNamespace,
476+
squidPods.Items[0].Name,
477+
"-c", "squid",
478+
"--", "squid", "-k", "reconfigure",
479+
)
480+
output, err := reconfigureCmd.CombinedOutput()
481+
o.Expect(err).NotTo(o.HaveOccurred(), "squid reconfigure failed: %s", string(output))
479482

483+
g.By("Updating trustedCA ConfigMap with new CA")
480484
cm, err := clients.KubeClient.CoreV1().ConfigMaps("openshift-config").Get(ctx, configMapName, metav1.GetOptions{})
481485
o.Expect(err).NotTo(o.HaveOccurred())
482-
cm.Data["ca-bundle.crt"] = string(newCAPEM)
486+
cm.Data["ca-bundle.crt"] = string(newCACertPEM)
483487
_, err = clients.KubeClient.CoreV1().ConfigMaps("openshift-config").Update(ctx, cm, metav1.UpdateOptions{})
484488
o.Expect(err).NotTo(o.HaveOccurred())
485489

@@ -516,7 +520,7 @@ func testNoProxy() {
516520
o.Expect(err).NotTo(o.HaveOccurred())
517521

518522
g.By("Deploying Squid forward proxy")
519-
proxyURL, _, proxyNS, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
523+
_, httpsProxyURL, _, proxyNS, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
520524
g.DeferCleanup(func() {
521525
g.GinkgoWriter.Println("cleaning up: removing Squid proxy")
522526
proxyCleanup()
@@ -540,15 +544,15 @@ func testNoProxy() {
540544

541545
g.By("Setting component-scoped proxy with noProxy")
542546
operatorAuth.Spec.Proxy = operatorv1.AuthenticationProxyConfig{
543-
HTTPSProxy: proxyURL,
547+
HTTPSProxy: httpsProxyURL,
544548
NoProxy: []string{issuerURL.Hostname()},
545549
}
546550

547551
_, err = clients.OperatorClient.OperatorV1().Authentications().Update(ctx, operatorAuth, metav1.UpdateOptions{})
548552
o.Expect(err).NotTo(o.HaveOccurred())
549553

550554
g.By("Waiting for operator to reconcile proxy config")
551-
err = test.WaitForClusterOperatorAvailableNotProgressingNotDegraded(t, clients.ConfigClient.ConfigV1(), "authentication")
555+
err = test.WaitForOperatorToPickUpChanges(t, clients.ConfigClient.ConfigV1(), "authentication")
552556
o.Expect(err).NotTo(o.HaveOccurred())
553557

554558
g.By("Creating Keycloak test user and group")

0 commit comments

Comments
 (0)