Skip to content

Commit 7026f96

Browse files
committed
Add integration test to check token timeouts
Signed-off-by: Simo Sorce <[email protected]>
1 parent 94bccdb commit 7026f96

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package integration
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
kerrors "k8s.io/apimachinery/pkg/api/errors"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
restclient "k8s.io/client-go/rest"
10+
11+
"github.com/openshift/origin/pkg/cmd/util/tokencmd"
12+
oauthapi "github.com/openshift/origin/pkg/oauth/apis/oauth"
13+
oauthvalidation "github.com/openshift/origin/pkg/oauth/apis/oauth/validation"
14+
oauthclient "github.com/openshift/origin/pkg/oauth/generated/internalclientset/typed/oauth/internalversion"
15+
userclient "github.com/openshift/origin/pkg/user/generated/internalclientset/typed/user/internalversion"
16+
testutil "github.com/openshift/origin/test/util"
17+
testserver "github.com/openshift/origin/test/util/server"
18+
)
19+
20+
func TestOAuthTimeout(t *testing.T) {
21+
testTimeout := int32(900)
22+
masterOptions, err := testserver.DefaultMasterOptions()
23+
if err != nil {
24+
t.Fatal(err)
25+
}
26+
masterOptions.OAuthConfig.TokenConfig.AccessTokenTimeoutSeconds = &testTimeout
27+
defer testserver.CleanupMasterEtcd(t, masterOptions)
28+
29+
clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterOptions)
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
34+
clientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
35+
if err != nil {
36+
t.Fatal(err)
37+
}
38+
oauthClient := oauthclient.NewForConfigOrDie(clientConfig)
39+
40+
// Use the server and CA info
41+
anonConfig := restclient.AnonymousClientConfig(clientConfig)
42+
43+
{
44+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
45+
ObjectMeta: metav1.ObjectMeta{Name: "defaulttimeout"},
46+
RespondWithChallenges: true,
47+
RedirectURIs: []string{"http://localhost"},
48+
GrantMethod: oauthapi.GrantHandlerAuto,
49+
})
50+
if err != nil {
51+
t.Fatal(err)
52+
}
53+
54+
testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, 900)
55+
}
56+
57+
{
58+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
59+
ObjectMeta: metav1.ObjectMeta{Name: "notimeout"},
60+
RespondWithChallenges: true,
61+
RedirectURIs: []string{"http://localhost"},
62+
AccessTokenTimeoutSeconds: new(int32),
63+
GrantMethod: oauthapi.GrantHandlerAuto,
64+
})
65+
if err != nil {
66+
t.Fatal(err)
67+
}
68+
69+
testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, 0)
70+
}
71+
72+
// check that we get an error trying to set a client value that is less
73+
// than the allowable minimum
74+
{
75+
invalid := int32(oauthvalidation.MinFlushTimeout - 1)
76+
_, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
77+
ObjectMeta: metav1.ObjectMeta{Name: "notvalid"},
78+
RespondWithChallenges: true,
79+
RedirectURIs: []string{"http://localhost"},
80+
AccessTokenTimeoutSeconds: &invalid,
81+
GrantMethod: oauthapi.GrantHandlerAuto,
82+
})
83+
if err == nil {
84+
t.Errorf("The 'notvalid' test is supposed to fail!")
85+
}
86+
}
87+
88+
{
89+
min := int32(oauthvalidation.MinFlushTimeout)
90+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
91+
ObjectMeta: metav1.ObjectMeta{Name: "mintimeout"},
92+
RespondWithChallenges: true,
93+
RedirectURIs: []string{"http://localhost"},
94+
AccessTokenTimeoutSeconds: &min,
95+
GrantMethod: oauthapi.GrantHandlerAuto,
96+
})
97+
if err != nil {
98+
t.Fatal(err)
99+
}
100+
101+
token := testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, int(min))
102+
103+
// wait 50% of timeout time, then try token and see it still work
104+
time.Sleep(time.Duration(min/2) * time.Second)
105+
testTokenWorks(t, anonConfig, token, false)
106+
107+
// Then Ensure the token times out
108+
time.Sleep(time.Duration(min+1) * time.Second)
109+
testTokenWorks(t, anonConfig, token, true)
110+
}
111+
}
112+
113+
func testTokenWorks(t *testing.T, anonConfig *restclient.Config, token string, expectTimeout bool) {
114+
// Make sure we can use the token, and it represents who we expect
115+
userConfig := *anonConfig
116+
userConfig.BearerToken = token
117+
userClient, err := userclient.NewForConfig(&userConfig)
118+
if err != nil {
119+
t.Fatal(err)
120+
}
121+
122+
user, err := userClient.Users().Get("~", metav1.GetOptions{})
123+
if err != nil {
124+
if expectTimeout && kerrors.IsUnauthorized(err) {
125+
return
126+
}
127+
t.Errorf("Unexpected error getting user ~: %v", err)
128+
}
129+
if user.Name != "username" {
130+
t.Errorf("Expected username as the user, got %v", user)
131+
}
132+
}
133+
134+
func testTimeoutOAuthFlows(t *testing.T, tokens oauthclient.OAuthAccessTokenInterface, oauthClient *oauthapi.OAuthClient, anonConfig *restclient.Config, expectedTimeout int) string {
135+
var lastToken string
136+
137+
// token flow followed by code flow
138+
for _, tokenFlow := range []bool{true, false} {
139+
tokenOpts := tokencmd.NewRequestTokenOptions(anonConfig, nil, "username", "password", tokenFlow)
140+
if err := tokenOpts.SetDefaultOsinConfig(); err != nil {
141+
t.Fatal(err)
142+
}
143+
tokenOpts.OsinConfig.ClientId = oauthClient.Name
144+
tokenOpts.OsinConfig.RedirectUrl = oauthClient.RedirectURIs[0]
145+
token, err := tokenOpts.RequestToken()
146+
if err != nil {
147+
t.Fatal(err)
148+
}
149+
150+
// Make sure the token exists with the overridden time
151+
tokenObj, err := tokens.Get(token, metav1.GetOptions{})
152+
if err != nil {
153+
t.Fatal(err)
154+
}
155+
if tokenObj.TimeoutsIn != int32(expectedTimeout) {
156+
t.Errorf("Token flow=%v, expected timeout of %d, got %#v", tokenFlow, expectedTimeout, tokenObj.TimeoutsIn)
157+
}
158+
159+
testTokenWorks(t, anonConfig, token, false)
160+
161+
lastToken = token
162+
}
163+
164+
return lastToken
165+
}
166+
167+
func TestOAuthTimeoutNotEnabled(t *testing.T) {
168+
masterConfig, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI()
169+
if err != nil {
170+
t.Fatal(err)
171+
}
172+
defer testserver.CleanupMasterEtcd(t, masterConfig)
173+
174+
clientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
175+
if err != nil {
176+
t.Fatal(err)
177+
}
178+
oauthClient := oauthclient.NewForConfigOrDie(clientConfig)
179+
180+
// Use the server and CA info
181+
anonConfig := restclient.AnonymousClientConfig(clientConfig)
182+
183+
min := int32(150)
184+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
185+
ObjectMeta: metav1.ObjectMeta{Name: "shorttimeoutthatisignored"},
186+
RespondWithChallenges: true,
187+
RedirectURIs: []string{"http://localhost"},
188+
AccessTokenTimeoutSeconds: &min,
189+
GrantMethod: oauthapi.GrantHandlerAuto,
190+
})
191+
if err != nil {
192+
t.Fatal(err)
193+
}
194+
195+
token := testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, int(min))
196+
197+
// ensure the token does not timeout because the feature is not active by default
198+
time.Sleep(time.Duration(min+30) * time.Second)
199+
testTokenWorks(t, anonConfig, token, false)
200+
}

0 commit comments

Comments
 (0)