@@ -2,11 +2,12 @@ package component_proxy
22
33import (
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
3333var _ = 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
203193func 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
343341func 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