Skip to content
This repository was archived by the owner on May 17, 2024. It is now read-only.

Commit 977dd5a

Browse files
committed
Adds token e2e test
Signed-off-by: JoshVanL <[email protected]>
1 parent 497e02e commit 977dd5a

File tree

6 files changed

+187
-60
lines changed

6 files changed

+187
-60
lines changed

test/e2e/framework/framework.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type Framework struct {
2525
BaseName string
2626

2727
KubeClientSet kubernetes.Interface
28+
ProxyClient kubernetes.Interface
2829

2930
Namespace *corev1.Namespace
3031

@@ -82,6 +83,10 @@ func (f *Framework) BeforeEach() {
8283

8384
f.issuerURL, f.proxyURL = issuerURL, proxyURL
8485
f.issuerKeyBundle, f.proxyKeyBundle = issuerKeyBundle, proxyKeyBundle
86+
87+
By("Creating Proxy Client")
88+
f.ProxyClient, err = f.NewProxyClient()
89+
Expect(err).NotTo(HaveOccurred())
8590
}
8691

8792
// AfterEach deletes the namespace, after reading its events.
@@ -99,11 +104,37 @@ func (f *Framework) Helper() *helper.Helper {
99104
return f.helper
100105
}
101106

102-
func (f *Framework) NewValidRestConfig() (*rest.Config, error) {
107+
func (f *Framework) IssuerKeyBundle() *util.KeyBundle {
108+
return f.issuerKeyBundle
109+
}
110+
111+
func (f *Framework) IssuerURL() string {
112+
return f.issuerURL
113+
}
114+
115+
func (f *Framework) ClientID() string {
116+
return clientID
117+
}
118+
119+
func (f *Framework) NewProxyRestConfig() (*rest.Config, error) {
103120
return f.Helper().NewValidRestConfig(f.issuerKeyBundle, f.proxyKeyBundle,
104121
f.issuerURL, f.proxyURL, clientID)
105122
}
106123

124+
func (f *Framework) NewProxyClient() (kubernetes.Interface, error) {
125+
proxyConfig, err := f.NewProxyRestConfig()
126+
if err != nil {
127+
return nil, err
128+
}
129+
130+
proxyClient, err := kubernetes.NewForConfig(proxyConfig)
131+
if err != nil {
132+
return nil, err
133+
}
134+
135+
return proxyClient, nil
136+
}
137+
107138
func CasesDescribe(text string, body func()) bool {
108139
return Describe("[TEST] "+text, body)
109140
}

test/e2e/framework/helper/token.go

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,15 @@ import (
1313
"github.com/jetstack/kube-oidc-proxy/test/e2e/util"
1414
)
1515

16-
func (h *Helper) NewValidRestConfig(issuerBundle, proxyBundle *util.KeyBundle, issuerURL, proxyURL, clientID string) (*rest.Config, error) {
17-
signer, err := jose.NewSigner(jose.SigningKey{
18-
Algorithm: jose.SignatureAlgorithm("RS256"),
19-
Key: issuerBundle.Key,
20-
}, nil)
21-
if err != nil {
22-
return nil, fmt.Errorf("failed to initialise new jwt signer: %s", err)
23-
}
24-
25-
token := h.newValidToken(issuerURL, clientID)
16+
func (h *Helper) NewValidRestConfig(issuerBundle, proxyBundle *util.KeyBundle,
17+
issuerURL, proxyURL, clientID string) (*rest.Config, error) {
2618

27-
jwt, err := signer.Sign(token)
19+
// valid token with exp in 10 minutes
20+
tokenPayload := h.NewTokenPayload(issuerURL, clientID,
21+
time.Now().Add(time.Minute*10))
22+
signedToken, err := h.SignToken(issuerBundle, tokenPayload)
2823
if err != nil {
29-
return nil, fmt.Errorf("failed to sign jwt: %s", err)
30-
}
31-
32-
signedToken, err := jwt.CompactSerialize()
33-
if err != nil {
34-
return nil, err
24+
return nil, fmt.Errorf("failed to sign token %q: %s", tokenPayload, err)
3525
}
3626

3727
certPool := x509.NewCertPool()
@@ -51,13 +41,35 @@ func (h *Helper) NewValidRestConfig(issuerBundle, proxyBundle *util.KeyBundle, i
5141
}, nil
5242
}
5343

54-
func (h *Helper) newValidToken(issuerURL, clientID string) []byte {
44+
func (h *Helper) SignToken(issuerBundle *util.KeyBundle, tokenPayload []byte) (string, error) {
45+
signer, err := jose.NewSigner(jose.SigningKey{
46+
Algorithm: jose.SignatureAlgorithm("RS256"),
47+
Key: issuerBundle.Key,
48+
}, nil)
49+
if err != nil {
50+
return "", fmt.Errorf("failed to initialise new jwt signer: %s", err)
51+
}
52+
53+
jwt, err := signer.Sign(tokenPayload)
54+
if err != nil {
55+
return "", fmt.Errorf("failed to sign jwt: %s", err)
56+
}
57+
58+
signedToken, err := jwt.CompactSerialize()
59+
if err != nil {
60+
return "", err
61+
}
62+
63+
return signedToken, nil
64+
}
65+
66+
func (h *Helper) NewTokenPayload(issuerURL, clientID string, exp time.Time) []byte {
5567
// valid for 10 mins
5668
return []byte(fmt.Sprintf(`{
5769
"iss":"%s",
5870
"aud":["%s","aud-2"],
5971
"email":"[email protected]",
6072
"groups":["group-1","group-2"],
6173
"exp":%d
62-
}`, issuerURL, clientID, time.Now().Add(time.Minute*10).Unix()))
74+
}`, issuerURL, clientID, exp.Unix()))
6375
}

test/e2e/suite/cases/doc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ package cases
22

33
import (
44
_ "github.com/jetstack/kube-oidc-proxy/test/e2e/suite/cases/rbac"
5+
_ "github.com/jetstack/kube-oidc-proxy/test/e2e/suite/cases/token"
56
)

test/e2e/suite/cases/rbac/rbac.go

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,34 @@ import (
99
rbacv1 "k8s.io/api/rbac/v1"
1010
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
1111
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12-
"k8s.io/client-go/kubernetes"
1312

1413
"github.com/jetstack/kube-oidc-proxy/test/e2e/framework"
1514
)
1615

1716
var _ = framework.CasesDescribe("RBAC", func() {
1817
f := framework.NewDefaultFramework("rbac")
1918

20-
var rClient *kubernetes.Clientset
21-
JustBeforeEach(func() {
22-
config, err := f.NewValidRestConfig()
23-
Expect(err).NotTo(HaveOccurred())
24-
25-
rClient, err = kubernetes.NewForConfig(config)
26-
Expect(err).NotTo(HaveOccurred())
27-
})
28-
2919
It("should return with a forbidden request with a valid token without rbac", func() {
3020
By("Attempting to Get Pods")
31-
_, err := rClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
21+
_, err := f.ProxyClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
3222
if !k8sErrors.IsForbidden(err) {
3323
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
3424
}
3525

3626
By("Attempting to Get Services")
37-
_, err = rClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
27+
_, err = f.ProxyClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
3828
if !k8sErrors.IsForbidden(err) {
3929
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
4030
}
4131

4232
By("Attempting to Get Secrets")
43-
_, err = rClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
33+
_, err = f.ProxyClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
4434
if !k8sErrors.IsForbidden(err) {
4535
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
4636
}
4737

4838
By("Attempting to Get Nodes")
49-
_, err = rClient.CoreV1().Nodes().List(metav1.ListOptions{})
39+
_, err = f.ProxyClient.CoreV1().Nodes().List(metav1.ListOptions{})
5040
if !k8sErrors.IsForbidden(err) {
5141
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
5242
}
@@ -87,23 +77,23 @@ var _ = framework.CasesDescribe("RBAC", func() {
8777
Expect(err).NotTo(HaveOccurred())
8878

8979
By("Attempting to Get Pods")
90-
_, err = rClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
80+
_, err = f.ProxyClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
9181
Expect(err).NotTo(HaveOccurred())
9282

9383
By("Attempting to Get Services")
94-
_, err = rClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
84+
_, err = f.ProxyClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
9585
if !k8sErrors.IsForbidden(err) {
9686
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
9787
}
9888

9989
By("Attempting to Get Secrets")
100-
_, err = rClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
90+
_, err = f.ProxyClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
10191
if !k8sErrors.IsForbidden(err) {
10292
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
10393
}
10494

10595
By("Attempting to Get Nodes")
106-
_, err = rClient.CoreV1().Nodes().List(metav1.ListOptions{})
96+
_, err = f.ProxyClient.CoreV1().Nodes().List(metav1.ListOptions{})
10797
if !k8sErrors.IsForbidden(err) {
10898
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
10999
}
@@ -123,21 +113,21 @@ var _ = framework.CasesDescribe("RBAC", func() {
123113
Expect(err).NotTo(HaveOccurred())
124114

125115
By("Attempting to Get Pods")
126-
_, err = rClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
116+
_, err = f.ProxyClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
127117
Expect(err).NotTo(HaveOccurred())
128118

129119
By("Attempting to Get Services")
130-
_, err = rClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
120+
_, err = f.ProxyClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
131121
Expect(err).NotTo(HaveOccurred())
132122

133123
By("Attempting to Get Secrets")
134-
_, err = rClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
124+
_, err = f.ProxyClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
135125
if !k8sErrors.IsForbidden(err) {
136126
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
137127
}
138128

139129
By("Attempting to Get Nodes")
140-
_, err = rClient.CoreV1().Nodes().List(metav1.ListOptions{})
130+
_, err = f.ProxyClient.CoreV1().Nodes().List(metav1.ListOptions{})
141131
if !k8sErrors.IsForbidden(err) {
142132
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
143133
}
@@ -157,19 +147,19 @@ var _ = framework.CasesDescribe("RBAC", func() {
157147
Expect(err).NotTo(HaveOccurred())
158148

159149
By("Attempting to Get Pods")
160-
_, err = rClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
150+
_, err = f.ProxyClient.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
161151
Expect(err).NotTo(HaveOccurred())
162152

163153
By("Attempting to Get Services")
164-
_, err = rClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
154+
_, err = f.ProxyClient.CoreV1().Services(f.Namespace.Name).List(metav1.ListOptions{})
165155
Expect(err).NotTo(HaveOccurred())
166156

167157
By("Attempting to Get Secrets")
168-
_, err = rClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
158+
_, err = f.ProxyClient.CoreV1().Secrets(f.Namespace.Name).List(metav1.ListOptions{})
169159
Expect(err).NotTo(HaveOccurred())
170160

171161
By("Attempting to Get Nodes")
172-
_, err = rClient.CoreV1().Nodes().List(metav1.ListOptions{})
162+
_, err = f.ProxyClient.CoreV1().Nodes().List(metav1.ListOptions{})
173163
if !k8sErrors.IsForbidden(err) {
174164
Expect(fmt.Errorf("expected forbidden error, got=%s", err)).NotTo(HaveOccurred())
175165
}

test/e2e/suite/cases/token/token.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package token
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io/ioutil"
7+
"net/http"
8+
"time"
9+
10+
. "github.com/onsi/ginkgo"
11+
. "github.com/onsi/gomega"
12+
13+
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15+
16+
"github.com/jetstack/kube-oidc-proxy/test/e2e/framework"
17+
)
18+
19+
type wraperRT struct {
20+
transport http.RoundTripper
21+
token string
22+
}
23+
24+
func (w *wraperRT) RoundTrip(r *http.Request) (*http.Response, error) {
25+
r.Header.Add("Authorization", fmt.Sprintf("bearer %s", w.token))
26+
return w.transport.RoundTrip(r)
27+
}
28+
29+
var _ = framework.CasesDescribe("Token", func() {
30+
f := framework.NewDefaultFramework("token")
31+
32+
It("should error when tokens are wrong for the issuer", func() {
33+
By("No token should error")
34+
expectProxyUnauthorized(f, nil)
35+
36+
By("Bad token should error")
37+
expectProxyUnauthorized(f, []byte("bad token"))
38+
39+
By("Wrong issuer should error")
40+
expectProxyUnauthorized(f, f.Helper().NewTokenPayload(
41+
"incorrect-issuer", f.ClientID(), time.Now().Add(time.Minute)))
42+
43+
By("Wrong audience should error")
44+
expectProxyUnauthorized(f, f.Helper().NewTokenPayload(
45+
f.IssuerURL(), "wrong-aud", time.Now().Add(time.Minute)))
46+
47+
By("Token expires now")
48+
expectProxyUnauthorized(f, f.Helper().NewTokenPayload(
49+
f.IssuerURL(), f.ClientID(), time.Now()))
50+
51+
By("Valid token should return Kubernetes forbidden")
52+
client, err := f.NewProxyClient()
53+
Expect(err).NotTo(HaveOccurred())
54+
55+
// if does not return with Kubernetes forbidden error then error
56+
_, err = client.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
57+
if !k8sErrors.IsForbidden(err) {
58+
Expect(err).NotTo(HaveOccurred())
59+
}
60+
})
61+
})
62+
63+
func expectProxyUnauthorized(f *framework.Framework, tokenPayload []byte) {
64+
// build client using given token payload
65+
signedToken, err := f.Helper().SignToken(f.IssuerKeyBundle(), tokenPayload)
66+
Expect(err).NotTo(HaveOccurred())
67+
68+
proxyConfig, err := f.NewProxyRestConfig()
69+
Expect(err).NotTo(HaveOccurred())
70+
71+
client := http.DefaultClient
72+
client.Transport = &wraperRT{
73+
transport: proxyConfig.Transport,
74+
token: signedToken,
75+
}
76+
77+
// send request with signed token to proxy
78+
target := fmt.Sprintf("%s/api/v1/namespaces/%s/pods",
79+
proxyConfig.Host, f.Namespace.Name)
80+
81+
resp, err := client.Get(target)
82+
Expect(err).NotTo(HaveOccurred())
83+
84+
body, err := ioutil.ReadAll(resp.Body)
85+
Expect(err).NotTo(HaveOccurred())
86+
87+
// check body and status code the token was rejected
88+
if resp.StatusCode != http.StatusForbidden ||
89+
!bytes.Equal(body, []byte("Unauthorized")) {
90+
}
91+
Expect(fmt.Errorf("expected status code %d with body Unauthorized, got= %d %q",
92+
resp.StatusCode, body)).NotTo(HaveOccurred())
93+
}

test/e2e/suite/suite.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@ var (
1414
)
1515

1616
var _ = SynchronizedBeforeSuite(func() []byte {
17-
//var err error
18-
//env, err = environment.Create(1, 3)
19-
//if err != nil {
20-
// log.Fatalf("Error provisioning environment: %v", err)
21-
//}
17+
var err error
18+
env, err = environment.Create(1, 3)
19+
if err != nil {
20+
log.Fatalf("Error provisioning environment: %v", err)
21+
}
2222

23-
//cfg.KubeConfigPath = env.KubeConfigPath()
24-
//cfg.Kubectl = filepath.Join(env.RootPath(), "bin", "kubectl")
25-
//cfg.RepoRoot = env.RootPath()
26-
//cfg.Environment = env
23+
cfg.KubeConfigPath = env.KubeConfigPath()
24+
cfg.Kubectl = filepath.Join(env.RootPath(), "bin", "kubectl")
25+
cfg.RepoRoot = env.RootPath()
26+
cfg.Environment = env
2727

2828
cfg.KubeConfigPath = "/home/josh/.kube/kind-config-kube-oidc-proxy-e2e"
2929
cfg.Kubectl = "/home/josh/go/src/github.com/jetstack/kube-oidc-proxy/bin/kubectl"
@@ -42,10 +42,10 @@ var globalLogs map[string]string
4242

4343
var _ = SynchronizedAfterSuite(func() {},
4444
func() {
45-
//if env != nil {
46-
// if err := env.Destory(); err != nil {
47-
// log.Fatalf("Failed to destory environment: %s", err)
48-
// }
49-
//}
45+
if env != nil {
46+
if err := env.Destory(); err != nil {
47+
log.Fatalf("Failed to destory environment: %s", err)
48+
}
49+
}
5050
},
5151
)

0 commit comments

Comments
 (0)