Skip to content

Commit ccbb9ec

Browse files
Merge pull request #29911 from openshift-cherrypick-robot/cherry-pick-29906-to-release-4.18
[release-4.18] OCPBUGS-57329: Fix failed tests of e2e-aws-ovn-tls-13
2 parents 0c9d746 + fd80923 commit ccbb9ec

File tree

3 files changed

+90
-25
lines changed

3 files changed

+90
-25
lines changed

test/extended/oauth/oauthcertfallback.go

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ package oauth
22

33
import (
44
"context"
5+
"crypto/sha256"
56
"io/ioutil"
67
"os"
78
"path"
9+
"strings"
810

911
g "github.com/onsi/ginkgo/v2"
1012
o "github.com/onsi/gomega"
1113

1214
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1315
"k8s.io/apiserver/pkg/authentication/user"
14-
"k8s.io/client-go/rest"
1516
restclient "k8s.io/client-go/rest"
17+
e2e "k8s.io/kubernetes/test/e2e/framework"
1618
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
1719

1820
configv1 "github.com/openshift/api/config/v1"
@@ -58,9 +60,8 @@ var _ = g.Describe("[sig-auth][Feature:OAuthServer] OAuth server", func() {
5860
// openssl s_client shows the kube-control-plane-signer CA name sent as one of the acceptable client CAs, so use that.
5961
realCASecret, err := oc.AsAdmin().KubeClient().CoreV1().Secrets("openshift-kube-apiserver-operator").Get(context.Background(), "kube-control-plane-signer", metav1.GetOptions{})
6062
o.Expect(err).NotTo(o.HaveOccurred())
61-
6263
realCAPEM, ok := realCASecret.Data["tls.crt"]
63-
o.Expect(ok).NotTo(o.BeFalse())
64+
o.Expect(ok).To(o.BeTrue())
6465

6566
realCA, err := crypto.CertsFromPEM(realCAPEM)
6667
o.Expect(err).NotTo(o.HaveOccurred())
@@ -87,86 +88,128 @@ var _ = g.Describe("[sig-auth][Feature:OAuthServer] OAuth server", func() {
8788
o.Expect(err).NotTo(o.HaveOccurred())
8889

8990
fooUserConfig := oc.GetClientConfigForUser(tokenUser)
90-
o.Expect(err).NotTo(o.HaveOccurred())
91+
o.Expect(fooUserConfig).NotTo(o.BeNil())
9192
validToken := fooUserConfig.BearerToken
9293
o.Expect(validToken).ToNot(o.BeEmpty())
9394

9495
adminConfig := oc.AdminConfig()
9596
validCert := adminConfig.TLSClientConfig
9697

98+
// Cache certs in a map
99+
certs := map[string]restclient.TLSClientConfig{
100+
"validCert": validCert,
101+
"invalidCert": invalidCert,
102+
"noCert": noCert,
103+
}
104+
97105
for name, test := range map[string]struct {
98106
token string
99-
cert rest.TLSClientConfig
107+
certKey string // use "validCert", "invalidCert", or "noCert"
100108
expectedUser string
101109
errorExpected bool
102110
errorString string
103111
}{
104112
"valid token, valid cert": {
105113
token: validToken,
106-
cert: validCert,
107-
expectedUser: certUser,
114+
certKey: "validCert",
115+
expectedUser: certUser, // If cert is valid, it takes precedence over token (because client certs are stronger auth).
108116
},
117+
109118
"valid token, invalid cert": {
110119
token: validToken,
111-
cert: invalidCert,
120+
certKey: "invalidCert",
112121
expectedUser: tokenUser,
113122
},
123+
114124
"valid token, no cert": {
115125
token: validToken,
116-
cert: noCert,
126+
certKey: "noCert",
117127
expectedUser: tokenUser,
118128
},
129+
119130
"invalid token, valid cert": {
120131
token: invalidToken,
121-
cert: validCert,
132+
certKey: "validCert",
122133
expectedUser: certUser,
123134
},
135+
124136
"invalid token, invalid cert": {
125137
token: invalidToken,
126-
cert: invalidCert,
138+
certKey: "invalidCert",
127139
errorExpected: true,
128140
errorString: unauthorizedError,
129141
},
142+
130143
"invalid token, no cert": {
131144
token: invalidToken,
132-
cert: noCert,
145+
certKey: "noCert",
133146
errorExpected: true,
134147
errorString: unauthorizedError,
135148
},
149+
136150
"no token, valid cert": {
137151
token: noToken,
138-
cert: validCert,
152+
certKey: "validCert",
139153
expectedUser: certUser,
140154
},
155+
141156
"no token, invalid cert": {
142157
token: noToken,
143-
cert: invalidCert,
158+
certKey: "invalidCert",
144159
errorExpected: true,
145160
errorString: unauthorizedError,
146161
},
162+
147163
"no token, no cert": {
148164
token: noToken,
149-
cert: noCert,
165+
certKey: "noCert",
150166
errorExpected: true,
151167
errorString: anonymousError,
152168
},
153169
} {
154170
g.By(name)
171+
172+
// Skip if test requires validCert but kubeconfig doesn't have one
173+
if test.certKey == "validCert" && len(validCert.CertData) == 0 && validCert.CertFile == "" {
174+
e2e.Logf("Skipping test '%s': no available client certificate in kubeconfig", name)
175+
continue
176+
}
177+
155178
adminConfig := restclient.AnonymousClientConfig(oc.AdminConfig())
179+
adminConfig.TLSClientConfig = certs[test.certKey]
156180
adminConfig.BearerToken = test.token
157-
adminConfig.TLSClientConfig = test.cert
158181
adminConfig.CAData = oc.AdminConfig().CAData
159182

183+
tokenPrefix := test.token
184+
if strings.HasPrefix(test.token, "sha256~") && len(test.token) > len("sha256~")+6 {
185+
tokenPrefix = test.token[:len("sha256~")+6] + "..."
186+
}
187+
e2e.Logf("Test case '%s': token='%s', using cert='%s'\n", name, tokenPrefix, test.certKey)
188+
if len(adminConfig.TLSClientConfig.CertData) > 0 {
189+
certs, err := crypto.CertsFromPEM(adminConfig.TLSClientConfig.CertData)
190+
if err != nil {
191+
e2e.Logf("Failed to parse cert: %v\n", err)
192+
} else {
193+
for i, cert := range certs {
194+
fingerprint := sha256.Sum256(cert.Raw)
195+
e2e.Logf("Cert[%d]: Subject=%s, Issuer=%s, SHA256=%x%s\n",
196+
i, cert.Subject.String(), cert.Issuer.String(), fingerprint[:3], "xxxxxx")
197+
}
198+
}
199+
} else {
200+
e2e.Logf("no available client certificate in kubeconfig\n")
201+
}
202+
160203
userClient := userv1client.NewForConfigOrDie(adminConfig)
161204
user, err := userClient.UserV1().Users().Get(context.Background(), "~", metav1.GetOptions{})
162205

163206
if test.errorExpected {
164207
o.Expect(err).ToNot(o.BeNil())
165208
o.Expect(err.Error()).To(o.Equal(test.errorString))
166209
} else {
210+
o.Expect(err).To(o.BeNil())
167211
o.Expect(user).ToNot(o.BeNil())
168212
o.Expect(user.Name).To(o.Equal(test.expectedUser))
169-
o.Expect(err).To(o.BeNil())
170213
}
171214
}
172215
})

test/extended/oauth/well_known.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/json"
66
"net/http"
77
"net/url"
8-
"path"
98

109
g "github.com/onsi/ginkgo/v2"
1110
o "github.com/onsi/gomega"
@@ -46,10 +45,12 @@ var _ = g.Describe("[sig-auth][Feature:OAuthServer] well-known endpoint", func()
4645
o.Expect(err).NotTo(o.HaveOccurred())
4746
u, err := url.Parse("https://" + route.Spec.Host)
4847
o.Expect(err).NotTo(o.HaveOccurred())
49-
u.Path = path.Join(u.Path, "oauth/authorize")
48+
u.Path = u.ResolveReference(&url.URL{Path: "/oauth/authorize"}).Path
5049
authEndpointFromRoute := u.String()
51-
o.Expect(metadata.AuthorizationEndpoint).To(o.Equal(authEndpointFromRoute))
50+
o.Expect(metadata.AuthorizationEndpoint).To(o.Equal(authEndpointFromRoute), "authorization endpoint does not match route")
51+
5252
}
53+
5354
tlsClientConfig, err := rest.TLSConfigFor(oc.AdminConfig())
5455
o.Expect(err).NotTo(o.HaveOccurred())
5556

@@ -63,6 +64,15 @@ var _ = g.Describe("[sig-auth][Feature:OAuthServer] well-known endpoint", func()
6364

6465
resp, err := rt.RoundTrip(req)
6566
o.Expect(err).NotTo(o.HaveOccurred())
66-
o.Expect(resp.StatusCode).To(o.Equal(200))
67+
defer resp.Body.Close()
68+
69+
// When a Bearer token is present in the kubeconfig,
70+
// Go’s HTTP client (via rest.TLSConfigFor) uses it in the Authorization: Bearer <token> header.
71+
// The request is no longer anonymous — it's now authenticated as that user or service account.
72+
if oc.AdminConfig().BearerToken != "" {
73+
o.Expect(resp.StatusCode).To(o.Equal(403), "expected 403 when BearerToken is present")
74+
} else {
75+
o.Expect(resp.StatusCode).To(o.Equal(200), "expected 200 when no BearerToken is present")
76+
}
6777
})
6878
})

test/extended/user/basic.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,26 @@ var _ = g.Describe("[sig-auth][Feature:UserAPI]", func() {
4444
})
4545

4646
g.By("make sure that user/~ returns groups for unbacked users", func() {
47-
// make sure that user/~ returns groups for unbacked users
48-
expectedClusterAdminGroups := []string{"system:authenticated", "system:masters"}
47+
// Compatible with some setups use system:cluster-admins instead of system:masters
48+
allowedGroups := [][]string{
49+
{"system:authenticated", "system:masters"},
50+
{"system:authenticated", "system:cluster-admins"},
51+
}
52+
4953
clusterAdminUser, err := clusterAdminUserClient.Users().Get(context.Background(), "~", metav1.GetOptions{})
5054
if err != nil {
5155
t.Fatalf("unexpected error: %v", err)
5256
}
53-
if !reflect.DeepEqual(clusterAdminUser.Groups, expectedClusterAdminGroups) {
54-
t.Errorf("expected %v, got %v", expectedClusterAdminGroups, clusterAdminUser.Groups)
57+
58+
matched := false
59+
for _, expectedGroups := range allowedGroups {
60+
if reflect.DeepEqual(clusterAdminUser.Groups, expectedGroups) {
61+
matched = true
62+
break
63+
}
64+
}
65+
if !matched {
66+
t.Errorf("unexpected groups returned for user/~: got %v, expected one of %v", clusterAdminUser.Groups, allowedGroups)
5567
}
5668
})
5769

0 commit comments

Comments
 (0)